home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacTech 1 to 12
/
MacTech-vol-1-12.toast
/
Reference
/
the cmsp digests ('94-'97)
/
csmp digest Vol 3 No 067
< prev
next >
Wrap
Internet Message Format
|
1997-05-06
|
136KB
From: pottier@clipper.ens.fr (Francois Pottier)
Subject: csmp-digest-v3-067
Date: Mon, 14 Nov 1994 15:53:04 +0100 (MET)
C.S.M.P. Digest Mon, 14 Nov 94 Volume 3 : Issue 67
Today's Topics:
(Q) AppleScript & XCMD's
Can anyone help me with the Time Manager?
Dynamic Dialogs?
How to install your own templates using Macsbug 6.5d6???
IM: Networking book question
INIT Writing FAQ [1-3]
INIT Writing FAQ [2-3]
INIT Writing FAQ [3-3]
Linking 68k object files to PPC program
Network Programming
Stuck in SyncWait again
having trouble with AEInteractWithUser & drag manager
The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier
(pottier@clipper.ens.fr).
The digest is a collection of article threads from the internet newsgroup
comp.sys.mac.programmer. It is designed for people who read c.s.m.p. semi-
regularly and want an archive of the discussions. If you don't know what a
newsgroup is, you probably don't have access to it. Ask your systems
administrator(s) for details. If you don't have access to news, you may
still be able to post messages to the group by using a mail server like
anon.penet.fi (mail help@anon.penet.fi for more information).
Each issue of the digest contains one or more sets of articles (called
threads), with each set corresponding to a 'discussion' of a particular
subject. The articles are not edited; all articles included in this digest
are in their original posted form (as received by our news server at
nef.ens.fr). Article threads are not added to the digest until the last
article added to the thread is at least two weeks old (this is to ensure that
the thread is dead before adding it to the digest). Article threads that
consist of only one message are generally not included in the digest.
The digest is officially distributed by two means, by email and ftp.
If you want to receive the digest by mail, send email to listserv@ens.fr
with no subject and one of the following commands as body:
help Sends you a summary of commands
subscribe csmp-digest Your Name Adds you to the mailing list
signoff csmp-digest Removes you from the list
Once you have subscribed, you will automatically receive each new
issue as it is created.
The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest.
Questions related to the ftp site should be directed to
scott.silver@dartmouth.edu. Currently no previous volumes of the CSMP
digest are available there.
Also, the digests are available to WAIS users. To search back issues
with WAIS, use comp.sys.mac.programmer.src. With Mosaic, use
http://www.wais.com/wais-dbs/comp.sys.mac.programmer.html.
-------------------------------------------------------
>From Tom_Brodhurst-Hill@intouch.mpx.com.au (Tom Brodhurst-Hill)
Subject: (Q) AppleScript & XCMD's
Date: 31 Oct 1994 19:07:41 GMT
Organization: MacInTouch BBS
Can anyone tell me whether XCMD's (typically for HyperCard) can be included in
and accessed by a compiled AppleScript application, without running a
separate HyperCard process?
Thanks,
Tom
please email to tombh@intouch.mpx.com.au
and post too for others.
MacInTouch BBS
info@intouch.mpx.com.au Ph. 61 2 541 1287 BBS. 61 2 541 0799
*** Sent by FirstClass the graphical email system by SoftArc. Inc. ***
+++++++++++++++++++++++++++
>From lai@apple.com (Ed Lai)
Date: Mon, 31 Oct 1994 17:20:39 GMT
Organization: Apple
In article <29224926.900353@intouch.intouch.mpx.com.au>,
Tom_Brodhurst-Hill@intouch.mpx.com.au (Tom Brodhurst-Hill) wrote:
> Can anyone tell me whether XCMD's (typically for HyperCard) can be included in
> and accessed by a compiled AppleScript application, without running a
> separate HyperCard process?
> Thanks,
> Tom
> please email to tombh@intouch.mpx.com.au
> and post too for others.
> MacInTouch BBS
> info@intouch.mpx.com.au Ph. 61 2 541 1287 BBS. 61 2 541 0799
> *** Sent by FirstClass the graphical email system by SoftArc. Inc. ***
It depends on the XCMD, a lot of them can be used, but if they are
very dependent on HyperCard specifc callback or globals, then they
cannot.
Try to download the XCMD OSAX.
Generally the place to look for AppleScript related stuff is in
gaea.kgs.ukans.edu.
If it is just for the XCMD OSAX, you may try ftp.apple.com in
/pub/lai/osax.
It is an adaptor for AppleScript to use XCMDs. It also comes installed
with a number of XCMDs by Rinaldi as examples.
In theory you can try it with any other XCMD/XFCNs you got. However to
do that requires writing certain resources and that is not a easy
job if you are doing it the first time.
--
/* Disclaimer: All statments and opinions expressed are my own */
/* Edmund K. Lai */
/* Apple Computer, MS303-3A */
/* 20525 Mariani Ave, */
/* Cupertino, CA 95014 */
/* (408)974-6272 */
zW@h9cOi
---------------------------
>From anthonym@puree.ugcs.caltech.edu (Anthony Molinaro)
Subject: Can anyone help me with the Time Manager?
Date: 21 Oct 1994 08:09:59 GMT
Organization: California Institute of Technology, Pasadena
I worked on this piece of code for a friend using Symatec
THINK C which turns on the power to a digital I/O board,
delays for a certain number of ticks, and then turns the
power off. This was my first time programming on a Macintosh
and so I had to search a little bit to find out about Delay.
Now, he tells me he needs a delay time smaller than one tick.
I know that the time manager can do this but I have been
unable to get it to work. I guess my confusion arises in the
type declarations and getting all of the types to match for
functions InsXTime(), PrimeTime(), and such. The Inside
Macintosh doesn't have any examples in C and I have not been
able to accurately port the Pascal functions with the proper
type settings. My midterms are quickly approaching but I
promised I would help him out, so any help that anyone could
give would be .
/* Here is the original code */
void Play(int note, unsigned long time)
{ long finalTicks;
short error;
/* turn on power for port,line: portout, lineout */
error = DIG_Out_Line(4, notes[note].portout, notes[note].line, 1);
chkerr("DIG_Out_Line",error);
/* if power is on delay */
if(error == 0)
Delay(time,&finalTicks);
/* turn off power */
error = DIG_Out_Line(4, notes[note].portout, notes[note].line, 0);
chkerr("DIG_Out_Line",error);
}
/* Here is what I tryed */
/* global variables */
int note;
TMTask tblah;
pascal void MyTimeTask(void)
{ DIG_Out_Line(4, notes[note].portout, notes[note].line, 0);
}
void MyDelay(unsigned long time)
{ tblah.tmAddr = &MyTimeTask();
tblah.tmWakeUp = 0;
tblah.tmReserved = 0;
InsXTime(&tblah);
PrimeTime(&tblah,time);
}
This didn't work, and I don't have a lot of time to figure out
why, so if anyone has any ideas I'm open to them. Thanks in
advance. Reply through e-mail if possible.
=====================================================================
Anthony Molinaro
anthonym@ugcs.caltech.edu
+++++++++++++++++++++++++++
>From Carl R. Osterwald <carl_osterwald@nrel.gov>
Date: Fri, 21 Oct 1994 17:23:44 GMT
Organization: National Renewable Energy Laboratory
In article <387t0n$3rr@gap.cco.caltech.edu> Anthony Molinaro,
anthonym@puree.ugcs.caltech.edu writes:
>Now, he tells me he needs a delay time smaller than one tick.
>I know that the time manager can do this but I have been
>unable to get it to work. I guess my confusion arises in the
>type declarations and getting all of the types to match for
>functions InsXTime(), PrimeTime(), and such. The Inside
Here is an example of a Time Manager task:
typedef struct
{
TMTask tm_task;
long A5;
} time_info;
Initialization:
timer_rec.tm_task.tmAddr = (TimerProcPtr)&time_task;
timer_rec.tm_task.tmWakeUp = 0;
timer_rec.tm_task.tmReserved = 0;
timer_rec.A5 = SetCurrentA5();
InsXTime( (QElemPtr)&timer_rec );
PrimeTime( (QElemPtr)timer_rec, period ); <<-- This starts the task
static void time_task (void)
{
time_info *timer_rec;
long current_A5;
asm
{
MOVE.L A1,timer_rec
MOVE.L A5,current_A5
};
SetA5(timer_rec->A5);
PrimeTime( (QElemPtr)timer_rec, period ); <<-- This restarts the task
SetA5(current_A5);
} // time_task
You can access your globals between the SetA5 calls. Because the time
task runs as an interrupt, it is best to minimize processing inside. In
your case, I would just set a global flag that is polled in the main
event loop to see if it is time to turn the device on or off.
+++++++++++++++++++++++++++
>From h+@nada.kth.se (Jon W{tte)
Date: Fri, 21 Oct 1994 18:48:34 +0100
Organization: Royal Institute of Something or other
In article <387t0n$3rr@gap.cco.caltech.edu>,
anthonym@puree.ugcs.caltech.edu (Anthony Molinaro) wrote:
>Now, he tells me he needs a delay time smaller than one tick.
>I know that the time manager can do this but I have been
>unable to get it to work. I guess my confusion arises in the
All you need is the system call Microseconds. You can write
your own Delay.
Cheers,
/ h+
--
Jon Wätte (h+@nada.kth.se), Hagagatan 1, 113 48 Stockholm, Sweden
Not speaking for the Microsoft Corporation.
+++++++++++++++++++++++++++
>From gbolsinga@aol.com (GBolsinga)
Date: 24 Oct 1994 17:20:05 -0400
Organization: America Online, Inc. (1-800-827-6364)
In article <387t0n$3rr@gap.cco.caltech.edu>,
anthonym@puree.ugcs.caltech.edu (Anthony Molinaro) writes:
>pascal void MyTimeTask(void)
>{ DIG_Out_Line(4, notes[note].portout, notes[note].line, 0);
>}
Look at the other sample code: it looks good. Another problem might
be that this function DIG_Out_Line can't move memory.
MyTimeTask executes at interupt time, so just set a global, and in
your idle in your event loop check for the global changing and then
call your function.
Greg Bolsinga
MPI Multimedia
+++++++++++++++++++++++++++
>From Tim Dorcey <td11@cornell.edu>
Date: 25 Oct 1994 19:01:49 GMT
Organization: Cornell University
In article <AACDBD82966813F759@klkmac005.nada.kth.se> Jon W{tte,
h+@nada.kth.se writes:
>All you need is the system call Microseconds. You can write
>your own Delay.
Do anyone know where the Microseconds call is documented? I stumbled
upon it in <Timer.h>, but can't find documentation for it anywhere. Is
it safe to assume that it is available on any system that has the
"Revised Time Manager?" I had written my own version, using
InsTime/RmvTime, which seems to work fine, but I'd just as soon use the
system call if it's equally available.
Tim Dorcey
Tim_Dorcey@cornell.edu
---------------------------
>From joey@caseware.com (Joey Caturay)
Subject: Dynamic Dialogs?
Date: Thu, 13 Oct 1994 15:15:23 GMT
Organization: CaseWare
I seem to recall a MacTutor/Tech article about writing dynamic dialogs (i.e.
dialogs in which controls change based on a selection in the dialog. The
Metrowerks Project Preference dialog is an example).
Is there source anywhere for dynamic dialogs?
Thanks,
joey
+++++++++++++++++++++++++++
>From johns@efn.org (John Selhorst)
Date: Fri, 14 Oct 1994 01:07:40 GMT
Organization: hisself
In article <joey.23.2E9D4F0B@caseware.com>, joey@caseware.com (Joey
Caturay) wrote:
> I seem to recall a MacTutor/Tech article about writing dynamic dialogs (i.e.
> dialogs in which controls change based on a selection in the dialog. The
> Metrowerks Project Preference dialog is an example).
>
> Is there source anywhere for dynamic dialogs?
>
> Thanks,
>
> joey
There are some nice snippets with dynamic dialogs on the developer CD and
probably on ftp.apple.com or whatever it's called now.
Johnny
johns@efn.org
+++++++++++++++++++++++++++
>From gurgle@dnai.com (Pete Gontier)
Date: Sat, 15 Oct 1994 02:39:20 -0800
Organization: Integer Poet Software
In article <joey.23.2E9D4F0B@caseware.com>, joey@caseware.com (Joey
Caturay) wrote:
> I seem to recall a MacTutor/Tech article about writing dynamic dialogs (i.e.
> dialogs in which controls change based on a selection in the dialog. The
> Metrowerks Project Preference dialog is an example).
> Is there source anywhere for dynamic dialogs?
Just get creative with HideDItem and ShowDItem. I recently implemented a
NewsWatcher-style dialog this way (and it was no coincidence...). There's
a popup menu at the top from which the user can select a set of dialog
items. The items always exist, but most of them are hidden most of the
time. Creating this dialog can be a pain unless you have a cool dialog
editor like the one in Resorcerer which actually lets you show and hide
ranges of items in the same way the Dialog Manager will do at run-time.
(It's been
This all said, if you're contemplating doing this, it may also be the case
that you are running into other limitations of the Dialog Manager.
Consider using something else, like any one of the several commercial
view-management systems (off the top of my head, QuickApp, AppsToGo,
MacApp, TCL, PowerPlant, FaceIt), or roll your own. (It's not all that
hard if all you want is a list of items like the Dialog Manager tracks.
Trees get messy, of course.)
--
Pete Gontier // CTO, Integer Poet Software // gurgle@dnai.com
"A Princeton Review executive said the whole affair was not that important
and offered to relinquish the Kaplan domain name 'for a case of beer'."
-- Chris Gulker, SF Examiner
+++++++++++++++++++++++++++
>From gurgle@dnai.com
Date: 14 Oct 94 21:39 GMT+0300
Organization: (none)
In article <joey.23.2E9D4F0B@caseware.com>, joey@caseware.com (Joey
Caturay) wrote:
> I seem to recall a MacTutor/Tech article about writing dynamic dialogs (i.e.
> dialogs in which controls change based on a selection in the dialog. The
> Metrowerks Project Preference dialog is an example).
> Is there source anywhere for dynamic dialogs?
Just get creative with HideDItem and ShowDItem. I recently implemented a
NewsWatcher-style dialog this way (and it was no coincidence...). There's
a popup menu at the top from which the user can select a set of dialog
items. The items always exist, but most of them are hidden most of the
time. Creating this dialog can be a pain unless you have a cool dialog
editor like the one in Resorcerer which actually lets you show and hide
ranges of items in the same way the Dialog Manager will do at run-time.
(It's been
This all said, if you're contemplating doing this, it may also be the case
that you are running into other limitations of the Dialog Manager.
Consider using something else, like any one of the several commercial
view-management systems (off the top of my head, QuickApp, AppsToGo,
MacApp, TCL, PowerPlant, FaceIt), or roll your own. (It's not all that
hard if all you want is a list of items like the Dialog Manager tracks.
Trees get messy, of course.)
--
Pete Gontier // CTO, Integer Poet Software // gurgle@dnai.com
"A Princeton Review executive said the whole affair was not that important
and offered to relinquish the Kaplan domain name 'for a case of beer'."
-- Chris Gulker, SF Examiner
+++++++++++++++++++++++++++
>From ivan_cavero_belaunde@avid.com (Ivan Cavero Belaunde)
Date: 18 Oct 1994 15:49:43 GMT
Organization: Avid Technology, Inc.
In article <gurgle-1510940239200001@dynamic-215.dnai.com>, gurgle@dnai.com
(Pete Gontier) wrote:
> In article <joey.23.2E9D4F0B@caseware.com>, joey@caseware.com (Joey
> Caturay) wrote:
>
> > I seem to recall a MacTutor/Tech article about writing dynamic dialogs
(i.e.
> > dialogs in which controls change based on a selection in the dialog. The
> > Metrowerks Project Preference dialog is an example).
> > Is there source anywhere for dynamic dialogs?
>
> Just get creative with HideDItem and ShowDItem. I recently implemented a
> NewsWatcher-style dialog this way (and it was no coincidence...). There's
> a popup menu at the top from which the user can select a set of dialog
> items. The items always exist, but most of them are hidden most of the
> time. Creating this dialog can be a pain unless you have a cool dialog
> editor like the one in Resorcerer which actually lets you show and hide
> ranges of items in the same way the Dialog Manager will do at run-time.
> (It's been
I thought NewsWatcher used AppendDITL, RemoveDITL, etc. I do remember
John's sample code from disinfectant containing routines along the lines
of AppendDITL and RemoveDITL to allow you to append and remove items to
the dialog (the Sys7/CTB routines of the same names work as long as you
DON'T use 'ictb' resources - otherwise they can crash horribly). I don't
have any source, but you might also want to look at either the QuickTime
Sequence Grabber Panel Component API or the Sound Control Panel Component
API for some pointers and ideas - it defines a clean layer between a main
piece of code that you write that controls the main dialog (ie the NW
popup menu or the "scrolling icon item" list in CW) and "plug-in"
subcomponents that control the independent panels.
-Ivan
- --
Ivan Cavero Belaunde (ivan_cavero_belaunde@avid.com)
Avid VideoShop Lead
Avid Technology, Inc.
Disclaimer: All views expressed are entirely my own and do not
reflect the opinions of Avid Technology, Inc.
+++++++++++++++++++++++++++
>From reed@medicine.wustl.edu (Thomas Reed)
Date: Tue, 18 Oct 1994 11:21:13 -0500
Organization: Washington University
In article <gurgle-1510940239200001@dynamic-215.dnai.com>, gurgle@dnai.com
(Pete Gontier) wrote:
>In article <joey.23.2E9D4F0B@caseware.com>, joey@caseware.com (Joey
>Caturay) wrote:
>
>> I seem to recall a MacTutor/Tech article about writing dynamic dialogs
>
>Just get creative with HideDItem and ShowDItem.
The method I like better is to set up your dialog with a "base" DITL,
containing whatever controls are going to be static for all settings.
This might contain your OK and Cancel buttons and a pop-up, if that's the
method you want to use to switch to a different set of controls. Then,
you define a separate DITL for each setting (say you have an options
dialog with three different options topics selectable on a pop-up menu,
you use 3 different DITLs, one for each topic). Make sure that the new
DITL can be overlayed on the "base" DITL the way you want it. I believe
that you may also want to specify that the "base" DLOG is not initially
visible.
Then, in your program, you use AppendDITL to overlay the DITLs. Just open
your base DLOG, then call AppendDITL to overlay the current setting on the
base DITL. The item numbers for the one you're adding will be bumped up
by the number of items in your base DITL.
Then, when the user switches to a different set of controls, you use
ShortenDITL to remove the old controls and AppendDITL to add the new set.
You've of course also got to take into account which set of controls
you're using in your dialog handling routines, as item #5 under one
setting may not be the same as item #5 under another. However, this is
not too hard to do.
I believe that this is the way that NewsWatcher does things.
-Thomas
=====================================================
Thomas Reed Washington University
reed@telesphere.wustl.edu Medical School
reed@medicine.wustl.edu Saint Louis, MO
- ---------------------------------------------------
Clothes make the man. Naked people have little or no
influence on society. -- Mark Twain
=====================================================
Opinions posted are not the opinions of Wash. U.
+++++++++++++++++++++++++++
>From bb@lightside.com (Bob Bradley)
Date: Mon, 17 Oct 1994 03:22:02 -0800
Organization: SS Software Inc.
In article <ivan_cavero_belaunde-1810941144230001@predator.avid.com>,
ivan_cavero_belaunde@avid.com (Ivan Cavero Belaunde) wrote:
> I thought NewsWatcher used AppendDITL, RemoveDITL, etc. I do remember
> John's sample code from disinfectant containing routines along the lines
> of AppendDITL and RemoveDITL to allow you to append and remove items to
> the dialog (the Sys7/CTB routines of the same names work as long as you
> DON'T use 'ictb' resources - otherwise they can crash horribly).
Any dialog with an ictb resource can't use AppendDITL/ShortenDITL? Is
there any other way to get the functionality of those two routines when
using dialogs with ictb resources without modifying the DITL in memory
directly?
I had a lot problems in the past with AppendDITL and ShortenDITL and could
never figure it out until you mentioned they didn't work with ictb
resources. I end up using the Show/Hide method but, when working with
dialogs with a lot of items, it gets difficult.
+++++++++++++++++++++++++++
>From rmah@panix.com (Robert Mah)
Date: Tue, 18 Oct 1994 18:15:26 -0500
Organization: One Step Beyond
Jason_Titus@odsnet.com wrote:
) I have been trying to work out a solution to a problem where I have a
) base window and can have a thousand or so possible midifications. It
) sounds like having these numerous DITL's and appending them would be
) the best solutions,but -
)
) how do I create DITLs? I can't find real descriptions of their format..
) My goal is to be able to create DITLs from text files of information
) (ie - a text file made up of checkbox titles) so I can easily create
) thousands of windows.
The usual way is to use ResEdit's or Resorcerer's graphical editors.
However given that you want to parse a text file to create user interfaces,
and assuming that the text file is not in rez format, I think you're going
to have to write a parser and create windows on the fly. That is, don't
use DITL and DLOG resources, but instead operate directly at the Window
Manager, Control Manager, List Manager and TextEdit levels.
Depending upon the complexity of your "interface description language",
this might not be too hard or it might be a royal pain in the...
Cheers,
Rob
_____________________________________________________________________
Robert S. Mah Software Development +1.212.947.6507
One Step Beyond and Network Consulting rmah@panix.com
+++++++++++++++++++++++++++
>From leonardr@netcom.com (Leonard Rosenthol)
Date: Wed, 19 Oct 1994 21:47:29 GMT
Organization: Aladdin Systems, Inc.
In article <bb-1710940322020001@user31.lightside.com>, bb@lightside.com
(Bob Bradley) wrote:
> In article <ivan_cavero_belaunde-1810941144230001@predator.avid.com>,
> ivan_cavero_belaunde@avid.com (Ivan Cavero Belaunde) wrote:
>
> > I thought NewsWatcher used AppendDITL, RemoveDITL, etc. I do remember
> > John's sample code from disinfectant containing routines along the lines
> > of AppendDITL and RemoveDITL to allow you to append and remove items to
> > the dialog (the Sys7/CTB routines of the same names work as long as you
> > DON'T use 'ictb' resources - otherwise they can crash horribly).
>
> Any dialog with an ictb resource can't use AppendDITL/ShortenDITL? Is
> there any other way to get the functionality of those two routines when
> using dialogs with ictb resources without modifying the DITL in memory
> directly?
>
That info about 'ictb's is NOT true. The System routines AppendDITL
and ShortenDITL will work just fine with ictb's GIVEN THE LIMITATIONS of
ictb resources (like they suck big time!).
Leonard
- ------------------------------------------------------------------------
Leonard Rosenthol Internet: leonardr@netcom.com
Director of Advanced Technology AppleLink: MACgician
Aladdin Systems, Inc. GEnie: MACgician
+++++++++++++++++++++++++++
>From ivan_cavero_belaunde@avid.com (Ivan Cavero Belaunde)
Date: 21 Oct 1994 14:44:58 GMT
Organization: Avid Technology, Inc.
In article <bb-1710940322020001@user31.lightside.com>, bb@lightside.com
(Bob Bradley) wrote:
> In article <ivan_cavero_belaunde-1810941144230001@predator.avid.com>,
> ivan_cavero_belaunde@avid.com (Ivan Cavero Belaunde) wrote:
> > I thought NewsWatcher used AppendDITL, RemoveDITL, etc. I do remember
> > John's sample code from disinfectant containing routines along the lines
> > of AppendDITL and RemoveDITL to allow you to append and remove items to
> > the dialog (the Sys7/CTB routines of the same names work as long as you
> > DON'T use 'ictb' resources - otherwise they can crash horribly).
>
> Any dialog with an ictb resource can't use AppendDITL/ShortenDITL? Is
> there any other way to get the functionality of those two routines when
> using dialogs with ictb resources without modifying the DITL in memory
> directly?
>
> I had a lot problems in the past with AppendDITL and ShortenDITL and could
> never figure it out until you mentioned they didn't work with ictb
> resources. I end up using the Show/Hide method but, when working with
> dialogs with a lot of items, it gets difficult.
Yeah, I had a lot of problems with those as well. Some of the problems
(text items changing colors, for example) hinted at a confused 'ictb', so
I stopped using one and everything was fine (it meant I had to use
useritems for some stuff, though). This suspicion was confirmed by someone
on the net who had worked on the AppendDITL/ShortenDITL code for Apple -
'ictb's are not supported by those calls.
Upon rereading my post above, I realize I imply John Norstad's
DITL-manipulation code supports 'ictb'. I actually don't know whether
that's the case or not - but it'd be easy to check if you need that
functionality.
-Ivan
- --
Ivan Cavero Belaunde (ivan_cavero_belaunde@avid.com)
Avid VideoShop Lead
Avid Technology, Inc.
Disclaimer: All views expressed are entirely my own and do not
reflect the opinions of Avid Technology, Inc.
+++++++++++++++++++++++++++
>From Peter_Gontier@novell.com (Pete Gontier)
Date: Mon, 24 Oct 1994 20:05:03 -0800
Organization: Novell, Inc., Walnut Creek Macintosh Site
In article <ivan_cavero_belaunde-1810941144230001@predator.avid.com>,
ivan_cavero_belaunde@avid.com (Ivan Cavero Belaunde) wrote:
> In article <gurgle-1510940239200001@dynamic-215.dnai.com>, gurgle@dnai.com
> (Pete Gontier) wrote:
>
> > Just get creative with HideDItem and ShowDItem. I recently implemented a
> > NewsWatcher-style dialog this way...
>
> I thought NewsWatcher used AppendDITL, RemoveDITL, etc...
I don't know for sure what NewsWatcher uses, but what I remember of the
way he stored his DITLs supports the notion that he's using AppendDITL,
etc.
When I said "NewsWatcher-style" I only meant the user interface is similar.
--
Views expressed here do not necessarily reflect the views of Novell.
+++++++++++++++++++++++++++
>From ivan_cavero_belaunde@avid.com (Ivan Cavero Belaunde)
Date: 31 Oct 1994 19:43:51 GMT
Organization: Avid Technology, Inc.
In article <leonardr-1910941347290001@leonardr.slip.netcom.com>,
leonardr@netcom.com (Leonard Rosenthol) wrote:
> In article <bb-1710940322020001@user31.lightside.com>, bb@lightside.com
> (Bob Bradley) wrote:
>
> > In article <ivan_cavero_belaunde-1810941144230001@predator.avid.com>,
> > ivan_cavero_belaunde@avid.com (Ivan Cavero Belaunde) wrote:
> >
> > > I thought NewsWatcher used AppendDITL, RemoveDITL, etc. I do remember
> > > John's sample code from disinfectant containing routines along the lines
> > > of AppendDITL and RemoveDITL to allow you to append and remove items to
> > > the dialog (the Sys7/CTB routines of the same names work as long as you
> > > DON'T use 'ictb' resources - otherwise they can crash horribly).
> >
> > Any dialog with an ictb resource can't use AppendDITL/ShortenDITL? Is
> > there any other way to get the functionality of those two routines when
> > using dialogs with ictb resources without modifying the DITL in memory
> > directly?
> That info about 'ictb's is NOT true. The System routines AppendDITL
> and ShortenDITL will work just fine with ictb's GIVEN THE LIMITATIONS of
> ictb resources (like they suck big time!).
Are you sure? I had an exchange on the net about a year/year and a half
ago with someone (his name slips me) that had worked on the
Append/RemoveDITL routines at Apple, and he explicitly mentioned that they
didn't support 'ictb's. This was at the time when I was having problems
with them: I kept getting items coming up in funny colors and fonts when I
appended them, as well as stray crashes inside UpdateDialog. Nuking the
'ictb's got rid of all those problems.
On a related note, how do they suck big time? My only beef is that they
are hard to edit unless you have Resorcerer, which is another one of the
bazillion reasons to get Resorcerer and skip ResEdit...
-Ivan
- --
Ivan Cavero Belaunde (ivan_cavero_belaunde@avid.com)
Avid VideoShop Lead
Avid Technology, Inc.
Disclaimer: All views expressed are entirely my own and do not
reflect the opinions of Avid Technology, Inc.
---------------------------
>From hsieh@netcom.com (Julia Hsieh)
Subject: How to install your own templates using Macsbug 6.5d6???
Date: Mon, 31 Oct 1994 17:25:57 GMT
Organization: NETCOM On-line Communication Services (408 261-4700 guest)
i've just started playing with custom templates in Macsbug, but since
the new version doesn't have a separate Debugger Prefs file with the
resources in it, how do i add my own custom templates?
also, i'm confused from one of the recent threads, is the Debugger
Prefs a file or a folder.
thanks.
-julia
--
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
If each day falls
inside each night,
there exists a well
where clarity is imprisoned.
We need to sit on the rim
of the well of darkness
and fish for fallen light
with patience.
-Pablo Neruda
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+++++++++++++++++++++++++++
>From johns@efn.org (John Selhorst)
Date: Tue, 1 Nov 1994 14:29:33 GMT
Organization: hisself
In article <hsiehCyJsFA.7vH@netcom.com>, hsieh@netcom.com (Julia Hsieh) wrote:
> i've just started playing with custom templates in Macsbug, but since
> the new version doesn't have a separate Debugger Prefs file with the
> resources in it, how do i add my own custom templates?
>
> also, i'm confused from one of the recent threads, is the Debugger
> Prefs a file or a folder.
>
> thanks.
> -julia
>
You've almost answered your own question. Yes, Debugger Prefs is a file
that goes into the system folder. It still works with MacsBug 6.5. If
you don't have one, make one yourself. You can make one with ResEdit.
Johnny
johns@efn.org
+++++++++++++++++++++++++++
>From jonasw@lysator.liu.se (Jonas Wallden)
Date: 1 Nov 1994 16:50:44 GMT
Organization: (none)
hsieh@netcom.com (Julia Hsieh) writes:
>i've just started playing with custom templates in Macsbug, but since
>the new version doesn't have a separate Debugger Prefs file with the
>resources in it, how do i add my own custom templates?
I'm running 6.5d6 and it uses a Debugger Prefs file.
You can also drop your templates and macros into the MacsBug file itself.
Just open it in ResEdit and paste them.
>also, i'm confused from one of the recent threads, is the Debugger
>Prefs a file or a folder.
It's a resource file, and should be located at the top level of your
System Folder.
>thanks.
>-julia
BTW, welcome on board! You just doubled the female/male ratio of Mac hackers
posting in this newsgroup... :-)
............... ....................... ........... ...............
jonas wallden internet applelink phone/fax
mac hacker jonasw@lysator.liu.se sw1369 +46-13-176084
+++++++++++++++++++++++++++
>From devon_hubbard@taligent.com (Devon Hubbard)
Date: Mon, 31 Oct 1994 18:57:56 GMT
Organization: Taligent, Inc.
In article <hsiehCyJsFA.7vH@netcom.com>, hsieh@netcom.com (Julia Hsieh) wrote:
>i've just started playing with custom templates in Macsbug, but since
>the new version doesn't have a separate Debugger Prefs file with the
>resources in it, how do i add my own custom templates?
Since most of the dcmds/templates in the old 'Debugger Prefs' were always
shipped with Macsbug, someone got smart at Apple (you know who you are :-)
and just put that stuff in Macsbug itself and then there was no need for
the separate prefs file. This didn't eliminate the usage of that prefs
file though. So if you want to add your own templates, macros, etc. go
right ahead and create a file called 'Debugger Prefs' and put your stuff
in there. The file type/creator is usually 'rsrc'/'RSED' but it really
doesn't matter to Macsbug as it'll open the rsrc fork of any type file
called 'Debugger Prefs'.
Also note that because Apple ships Macsbug this way, there is no need to
merge their prefs with yours when a new release comes out.
dEVoN
- -----------------------------------------------------------------------
Devon Hubbard Silicon Pilot
devon_hubbard@taligent.com Taligent, Inc
- -----------------------------------------------------------------------
"No amount of genius can overcome a preoccupation with detail." -Einstein
---------------------------
>From schultz@iastate.edu (Jonathan Schultz)
Subject: IM: Networking book question
Date: 28 Oct 94 07:08:51 GMT
Organization: Iowa State University, Ames, Iowa
Does IM: Networking totally supercede Inside AppleTalk?
Jonathan
schultz@iastate.edu
--
- -----------------
Jonathan Schultz
schultz@iastate.edu
+++++++++++++++++++++++++++
>From jumplong@aol.com (Jump Long)
Date: 29 Oct 1994 21:32:03 -0400
Organization: America Online, Inc. (1-800-827-6364)
In article <schultz.783328131@pv3449.vincent.iastate.edu>,
schultz@iastate.edu (Jonathan Schultz) writes:
>Does IM: Networking totally supercede Inside AppleTalk?
No it doesn't.
IM: Networking replaces the AppleTalk chapters of Inside Macintosh volumes
II, IV, V, and VI (the old Inside Macintosh volumes). IM: Networking
describes the Macintosh AppleTalk API. Inside AppleTalk describes the
AppleTalk *protocols* - not the API for any particular implementation of
AppleTalk.
While Inside AppleTalk isn't required to use most parts of the Macintosh
AppleTalk API, it is useful when debugging AppleTalk problems you may have
when using the Macintosh API because it describes the network packets and
describes how the protocol was designed to be used. To use some parts of
the Macintosh API, you must have Inside AppleTalk because the Macintosh
API doesn't build the request packets or disassemble the reply packets for
you. An example of that is using the .XPP driver to send AFP requests.
Since the system doesn't build those packets for you, you'll have to use
the information in Inside AppleTalk to know how to build them yourself.
- Jim Luther
---------------------------
>From Jaeger@fquest.com (Brian Stern)
Subject: INIT Writing FAQ [1-3]
Date: 28 Oct 1994 00:37:24 GMT
Organization: The University of Texas at Austin, Austin, Texas
Answers to Frequently Asked Questions about writing System Extensions
on the Macintosh Computer. Version 1.0 10/94
This document is Copyright © 1994 by Brian Stern.
I can be contacted by email at <Jaeger@fquest.com> on Internet.
The purpose of this FAQ list is to provide information on the writing
of system extensions. This arcane art is difficult to learn and the
existing information on the subject is spread around in various
places. Hopefully the information here will help new and old INIT
writers to write better INITs in less time.
The questions in this document are broken into two sections: System
Extensions and Trap Patches. While most extensions contain trap
patches these subjects seemed different so I have separated them.
FAQ lists like this one are an integral part of Usenet. When I
started reading Usenet news I assure you that I knew nothing about
writing extensions. I learned by posting questions to
comp.sys.mac.programmer and by reading other's questions and
responses. Let me take this space to give you a few tips on phrasing
of questions to newsgroups.
When asking a question try to make the title as descriptive as
possible. Most people don't have time to read every question posted
and will ignore posts whose titles are unclear or meaningless. Don't
post questions titled 'HELP, My program doesn't work', or worse
'URGENT NEED HELP with program'. I'm sure it's urgent to you, but
not to me. Always indicate that you're asking a questing by
including a (you guessed it) question mark. Consider these titles:
'Programmers make big salaries' and 'Programmers make big salaries?'
Don't waste people's time with the former when you mean the latter.
Another way to indicate a question is like this: '[Q] Programmers
make big salaries?'. Try to include one of the words 'who, what,
when, where, why, or how' in the titles of your questions. Your
questions are much more likely to be answered by someone who actually
knows the answer if your title is clear.
The code samples in this document were developed with Think C. You
may need to make some changes to use them with other development
systems. I've used inline assembly in many of the code samples. To
my eye this makes things more clear since it's obvious what's going
on. Not everyone agrees with this and not all development
environments provide inline assembly. It's possible to rewrite most
or all of this code by use of inline functions. If you're writing in
Pascal or using CodeWarrior you'll have to do it that way.
You'll be able to find information on general questions of Mac
programming in the FAQ list maintained by Jon Watte at:
ftp://nada.kth.se/pub/hacks/mac-faq/CSMP_PD_FAQ
If you have questions about writing extensions that aren't addressed
in this document or any comments about it feel free to send them to
me. If I know the answer or can find it out it may find its way into
a later version.
This document may be distributed freely as long as no changes are
made to it. It may not be distributed in ways in which the user must
pay for the document, other than reasonable download costs or costs
for the medium, without the consent of the author.
Thanks to the following people who provided sample code and made
constructive comments: Pete Gontier, Dair Grant, Chelly Green, Devon
Hubbard, Peter Lewis, Jim Walker, Jim Wintermyre.
- -------------------------------------------------------------------
System Extension Writing FAQ Outline:
System Extensions:
[1] What is an INIT, exactly?
[2] Should I write an INIT?
[3] Can I write an INIT that makes the application menu into a
hierarchical menu?
[4] Do I need to know assembler to write an INIT?
[5] Can you show me a sample INIT?
[6] Can I have global variables in my INIT?
[7] How do I debug an INIT?
[8] How do I write a Control Panel-INIT combination?
[9] How do I capture keystrokes?
[10] How can my extension get time periodically?
[11] How should an INIT manage memory?
[12] How do I get my INIT to turn itself off?
[13] How do I get my INIT to show its icon like all the other cool
INITs do?
[14] How do I show a dialog from my INIT?
[15] How do I maintain compatibility with future systems?
[16] Any tips for INIT writing?
Trap Patches:
[17] What exactly is a trap patch?
[18] What's the difference between a head patch and a tail patch?
[19] How do I patch a trap?
[20] How do I patch a register-based trap?
[21] Can you show me an example tail patch?
[22] How do I patch a selector-based trap?
[23] How do I patch a trap on the PPC?
[24] Can I write a fat trap?
[25] Tips?
[26] What other sources of information are available?
- -------------------------------------------------------------------
[1] What is an INIT, exactly?
An INIT is a type of code resource that is loaded into memory and
executed during the startup process. They're called INITs because
they're resources of type 'INIT'. INITs load at the end of the
startup process, after the hardware checks have been done and the
system has been started. The span of time during which INITs load
and execute is known as INIT time. Applications don't load until
after INIT time and in most cases the first application to load is
the Finder.
Because they load before all applications, INITs can modify the
system in a way that affects all applications. They can add new
functionalities and modify the way in which many processes occur on
the Mac. Apple often supplies new additions and updates to system
software as INITs. This includes things such as the Drag-and-Drop
Manager, Thread Manager, Speech Manager, and Sound Manager 3.0. At
some point these new features are rolled into a new software release
and eventually they are included in new ROMs, but they all start life
as INITs.
Apple recommends that the term 'system extension' be used when
communicating with non-programmers. This name carries the
implication that they extend the functionality of the system. You'll
see the terms 'INIT', 'extension', and 'system extension' used to
mean the same thing throughout this document.
Extensions are loaded in a defined order. Resources of type 'INIT'
can be found in files of type 'INIT' (System Extension), 'cdev'
(Control Panel), 'RDEV' (Chooser Device), 'appe' (application
extension), and 'scri' (script system extensions). In order to be
loaded, the INIT resource must be in one of these file types in one
of several locations in the System Folder.
Under system 7 INITs are loaded first from the Extensions Folder in
alphabetical order. INITs present in script system extension files
(filetype 'scri') load before INITs present in system extension files
(filetype 'INIT'). Next, any INITs in the Control Panels folder are
loaded in alphabetical order. Any INITs present at the root level of
the System Folder are loaded after that. This order of loading is
important if an extension is dependent on the presence of another
extension. For example, if an INIT resource in an INIT file named
'SpeakAll' is dependent on the presence of the 'Speech Manager'
extension, it either needs to have its name changed to something that
sorts after 'Speech Manager' or it has to be located in the Control
Panels folder, since extensions in the Control Panels folder load
after extensions in the Extensions Folder.
In system 6 the Extensions Folder and Control Panels Folders don't
exist. Extensions are simply loaded in alphabetical order from the
root level of the System Folder.
--
[2] Should I write an INIT?
System extensions are not easy to write. If this is your first
attempt at Mac programming, the answer to this question is NO. Many
experienced Mac programmers have never written one and don't intend
to.
There are a number of other ways to add functionality without writing
an extension. If you want to add functionality to a single
application then think about writing an FKEY. These are invoked by
hitting cmd-shift-number and perform an action at that time only.
The standard screen shot (cmd-shift-3) is one example.
Another user-invokable means of adding functionality is plug-in
modules. A number of commercial software packages support plug-ins
that can add functionality in a straightforward manner. This
includes PhotoShop, Quark Express, Hypercard and others.
Another means of adding functionality is the use of a background-only
application, AKA faceless-background application (fba). Fbas are
applications without a user interface. One type of fba is known as
an application extension. These are applications whose resource
files are of type 'appe'. They are placed in the extensions folder
(or the Startup Items Folder) and are started up after INIT time.
They can communicate with other processes by Apple Events and by
Gestalt selectors. If you don't need to patch a trap then an fba may
be the way to add functionality to the system. Since an fba runs as
a normal process there are some things that it can do that system
extensions cannot do (or at least cannot do safely), like launch
applications and send and receive Apple Events. An INIT resource in
the resource fork of an application extension in the Extensions
Folder will load normally at INIT time. See issue 9 of develop and
the Tech Note PS 2 - Background-Only Applications for more info.
Also consider an application that is started up by being placed in
the startup items folder. The Screen Saver 'Dark Side of the Mac' is
written in this way. Screen Savers are traditionally written as
extensions because extensions can have access to the mouse location
and all keyboard events. However an intelligently written
application can do the same and be more compatible.
If none of these things seems like it will work for you and you are
thinking something like 'I want X to happen every time a resource is
loaded', or otherwise add to or replace the system's functionality in
some way then an extension is probably what you need.
Remember that when developing system extensions you will be working
without a net.
--
[3] Can I write an INIT that makes the application menu into a
hierarchical menu?
Every couple of weeks someone posts a message on
comp.sys.mac.programmer entitled 'Neat idea for an init'. These
posts go on to describe some non-programmer's idea of a great INIT.
Invariably these posts fall into two groups: those that have already
been done, and those that should never be done. Think long and hard
about the design of an extension before starting to write it.
Consider your target audience. If it's only yourself then you can do
what you want. My first couple of extensions were just tests to see
if I could actually do it. The answer to the above question is:
Maybe you can but probably you shouldn't.
--
[4] Do I need to know assembler to write an extension?
Yes. Strictly speaking, the simplest extension that just beeps at
startup and doesn't hang around past INIT time requires no assembler.
However, any extension that does anything useful will require some
assembler in order to patch a trap or install a jGNEFilter. The
extension can be written mostly in a high level language like C or
Pascal, but there will be bits and pieces that need to be written in
assembler to keep the stack happy or to access parameters passed in
registers. Hopefully there will be enough sample code in this
document to get you on your way if your assembler is weak.
You will often need to inspect the disassembled source of your
extension. If your development environment doesn't allow this the
ResEdit Code Viewer will also allow you to inspect code resources.
It can be found at ftp://ftp.apple.com/dts/mac/tools/resedit/resedit-
extensions.hqx.
--
[5] Can you show me a sample INIT?
Here's the code for the 'Hello World' of INITs.
void main(void)
{
SysBeep( 5 );
}
Not very complicated is it? There are a number of additional things
that are required to make this work:
1) Set the project type to code resource.
2) Set the resource type to 'INIT'.
3) Set the resource ID to something (>= 128), and set the resource
name if desired.
4) Set the resource attributes to 'System Heap'.
5) Set the resource attributes to 'Locked'.
6) Set the filetype of the built code resource file to 'INIT' with
any creator signature.
7) Set the filename of the built code resource file to 'Hello World'.
Let me explain what each of these things does.
1) Because you're building a standalone code resource your compiler
needs to know this. This is how the compiler knows to use A4
addressing, rather than the A5 addressing used in applications.
2) As mentioned above, extensions are code resources of type 'INIT'.
3) Like any other resources they have IDs and can have names.
4) Setting the system heap flag places the code resource in the
system heap. While not strictly required for this sample, in most
other extensions we will want the code resource to remain in the
system heap so this flag must be set. During the process that loads
and executes INITs a small heap is created. Any memory allocation
done by the INIT will, by default occur in this heap. Also any
resources read into memory will, by default, go into this heap. If
the system heap flag isn't set for the INIT itself then the INIT will
be loaded into this temporary heap. When the INIT exits the heap is
disposed and anything in it is lost. If an INIT intends to stay
around past INIT time then it must have the system heap flag set.
5) The code resource should never move in memory so the Locked bit
is set. When a resource with the Locked bit is loaded into memory it
is loaded as low in the heap as possible. This is what we want since
the INIT resource will never be unlocked. It is poor design to not
set the Locked bit and to rely on the INIT to lock itself. In that
case the INIT will not be loaded low in the system heap. This isn't
fatal but will lead to fragmentation of the system heap.
Some INITs try to use MoveHHi/HLock to move themselves or associated
resources high in the system heap. MoveHHi is disabled for the
system heap. Since the system heap is dynamically sizable the
concept of the top of the heap is invalid. For this reason MoveHHi
does nothing when the handle being referred to is within the system
heap.
6) The filetype of 'INIT' gives you the generic extension icon, and
of course allows the extension to load and execute at INIT time.
7) Set the file name to something like 'Hello World'.
Once these things have been done you can build the code resource and
drag its file to the System Folder. The Finder should place it in
the Extensions Folder for you and it should have the generic
extension icon. When you restart you will hear the beep when the
extension is loaded.
Every extension must have a routine called 'main'. When the INIT
resource is loaded into memory during INIT time the system jumps to
the beginning of the code resource. The header of the code resource
will normally contain a branch instruction that branches to the main
routine. This routine does whatever it needs to do and then returns.
In this 'Hello World' extension all that the main routine does is
call SysBeep. In more substantial extensions the main routine will
do things like patch traps, install gestalt selectors, and load
resources into memory.
--
[6] Can I have global variables in my INIT?
Yes you can. The Think environment and the CodeWarrior environment
use A4-based addressing for global variables in code resources. The
base address of the extension is found in register A0 on entry to the
extension, and routines are provided to save this value and to set up
and restore register A4 when the INIT is entered later. (In fact the
standard header installed by Think C in code resources loads the
address of the code resource into A0 by use of pc-relative
addressing.) See the A4-Addressing section of your development
environment's manual for more information.
When writing extensions with the MPW compilers you may need to use an
A5-based method for accessing global variables. See the Apple tech
note 'StandAlone Code, ad nauseam' (#256) for more information on
this method. ftp://ftp.apple.com/dts/mac/tn/platforms.tools.pt/pt-
35-stand-alone-code.hqx
and
"Another take on Globals in Standalone Code", Keith Rollin
ftp://ftp.apple.com/dts/mac/docs/develop/develop.12.code/globals-in-
standalone-code.hqx
Here is some sample code using the Think C routines to illustrate
this:
/****Main*****************************************************/
void
main(void) //Main entry point of the extension
{
void *pToMe;
Boolean initedOK;
pToMe = GetA0(); //Save our address locally
RememberA0(); //Save our base address
SetUpA4(); //Set up A4-based addressing
initedOK = InitAll(); //Patch traps etc.
if ( initedOK )
{
//Make sure we stay around
DetachResource( RecoverHandle( pToMe) );
}
RestoreA4(); //Reset A4 to its value on entry
}
This code sample also illustrates one method extensions can use to
remain in memory after INIT time. Since extensions are code
resources they will be removed from memory when their resource files
are closed. This happens when the main routine exits. To avoid
this, DetachResource must be called with the handle to the code
resource. One common mistake with this is not having the code
resource marked system heap. If it's not marked system heap it will
be lost when the temporary heap is destroyed, whether it was detached
or not. The GetA0 routine used above is defined in the tips section
farther down in this document. Here are a few other methods for an
extension to detach itself:
void
main(void) //Another method
{
asm
{
RecoverHandle //A0 already holdss our address
move.L A0, -(A7) //DetachResource is stack-based
DetachResource //so push A0 onto the stack
}
}
void
main(void) //This method uses no assembler
{
DetachResource( Get1Resource( 'INIT', kOurResID ) );
}
--
[7] How do I debug an INIT?
Debugging is generally the most time consuming, difficult, and all-
around pain-in-the-neck part of producing good code. That goes
double for INITs. Unfortunately many parts of INITs must be debugged
with low level debuggers. The low level debuggers that I know about
are MacsBug, TMON, and Jasik's Debugger. MacsBug is free and is
available at ftp://ftp.apple.com/dts/mac/tools/macsbug/macsbug-6-
5d6.hqx. The two other low level debuggers are commercialware.
Jasik's debugger has the ability to do source level debugging of code
resources, like system extensions.
In most cases, your low level debugger of choice will load before
INIT time so it can be used to debug initialization of INITs. One
exception to this is Jasik's Debugger, which loads in two parts. One
of these is an extension that must load before your extension.
The debugger can be invoked by calling the Debugger() or DebugStr()
traps. Placing these trap calls in your code will drop you into the
low level debugger so that you can step through your code and inspect
registers or memory as needed.
One useful technique is to take advantage of Macsbug's ability to
process commands after a semicolon in a DebugStr call. The following
function can display information that you would otherwise have to
hunt down using hex offsets:
pascal void SomeFunction (arguments)
{
// ...
asm { MOVE.L fooP, A0 } // fooP can be any type
asm { MOVE.L sizeof(*fooP), D0 }
DebugStr ("\p ; dm rA0 rD0"); // dump (*fooP) in hex
// ...
}
If you haven't placed Debugger() calls in your code then you will
have to set a breakpoint in order to step through any trap patches or
other parts of your extension. Here are a couple of methods to do
that. If you have patched a trap, say GetResource, if you drop into
MacsBug and type 'il GetResource' MacsBug will begin to disassemble
at your patch. You can then set a breakpoint by typing 'br
GetResource' or br theaddress' where theaddress is the address in hex
of your patch or some part of it. Type 'brc' when you want to clear
all breakpoints. Using the A-trap commands will also work. 'atb
GetResource' will set a break and 'atc' will clear all A-trap
breakpoints.
If you want to set a breakpoint in some other part of your extension,
say in a jGNEFilter, then you need another way of finding its
location in memory. In MacsBug type 'hx syszone^' or just 'hx' to
set the current heap to the system heap (where your extension is
located). Type 'br ' (don't hit return yet) and then type cmd-D to
view the names of all the routines in the system heap that were
compiled with MacsBug names turned on (like yours, right?) Scroll
down until you find the name of your routine. Hit enter and the
command line should look like 'br yourRoutineName'. Hit enter again
and the breakpoint will be set. You can also simply type 'br
yourRoutineName' and MacsBug will find it for you. The zone must be
set to the zone containing the routine that you want to break on for
MacsBug to find it, so make sure to set the zone to the system zone.
Identifying your extension in the system heap is dependent on
compiling it with the MacsBug symbols option turned on. This inserts
Ascii versions of the names of each function in the compiled code in
such a way the MacsBug , and other debuggers can find these names.
Jasik's debugger uses a different method for identifying your code
that is based on SYM files, which are generated by your compiler.
The SYM files allows Jasik's debugger to do source level debugging of
INITs and other code resources.
I have used a two-project method, when developing INITs and other
code resources, that helps to cut down debugging time. Any extension
consists of essentially two parts: the initialization portion and the
implementation portion. The initialization portion detaches the
resource as described above, shows the icon, and often patches traps.
The implementation portion contains the actual trap patches. It is
quite possible, and desirable, to test the implementation portion in
the context of an application, rather than as an INIT. To accomplish
this your project consists of three parts, which for a simple case
would be three files.
TesterApp Project:
SetUpApplication.c Simple application shell that sets up
the trap patches and provides a
mechanism to call the traps
TrapPatches.c Code for the trap patches
INIT Project:
SetUpINIt.c Standard INIT setup; contains main
entry point; patches all necessary
traps
TrapPatches.c Code for the trap patches; same file as
in the TesterApp Project
The mechanism for calling the traps in SetUpApplication.c is usually
a menu item. In some cases it might be a dialog with several
buttons, each of which calls a particular trap. It isn't always
necessary to patch traps in your TesterApplication. Simply calling
the routines that implement the guts of the trap patches will often
be just as good. Having two projects, one that builds the tester
application and the other that builds the extension, allows you to
save time debugging and to be able to build the extension at any
time.
Writing and testing extensions involves multiple rounds of
'compiling-installing the INIT-rebooting-Stepping through the INIT in
a low level debugger'. Use of the two-project method will cut down
this time.
--
[8] How do I write a Control Panel-INIT combination?
System extensions generally have no interface. They do what they do
quietly and the user doesn't want to hear from them. In many cases
the user needs to set certain preferences. The natural mechanism for
this is to couple a control panel with an INIT. The problem of
course is how does the control panel communicate the changes to the
INIT. I won't discuss the general mechanisms of control panel
authoring here (see NIM: More Macintosh Toolbox, Chapter 8), but
there are several mechanisms available for communicating between
extensions and control panels.
The simplest mechanism and one that will work in the vast majority of
cases is for the extension to install a Gestalt selector. This
selector returns the address of a block of memory that holds
variables that control the actions of the extension. The control
panel calls the Gestalt selector, retrieves the address of the memory
block, and alters the values stored in the block as needed. In some
cases the memory block can contain a function pointer to a function
in the extension that needs to be called from the control panel.
Here is some sample code:
typedef struct CommonInfo{
void (*ResetINIT) (void);//function pointer to reset
//func
Boolean On;
};
#define kSignature 'BLAH' //Should be the sig of the INIT
static CommonInfo gInfo;
/**InstallGestaltSelector****************************************/
//In the INIT; runs at INIT time
OSErr
InstallGestaltSelector(void)
{
OSErr err;
err = NewGestalt( kSignature, OurSelector );
if ( err == noErr )
{
gInfo.ResetINIT = (void *) ResetFunction;
gInfo.On = TRUE;
}
return err;
}
/**OurSelector**************************************************/
//In the INIT
pascal OSErr
OurSelector( OSType theSelector, long *theResponse )
{
SetUpA4();
*theResponse = (long) &gInfo;
RestoreA4();
return noErr;
}
/**ResetFunction***********************************************/
//In the INIT
void
ResetFunction(void)
{
SetUpA4();
//Do something here
RestoreA4();
}
/**Close********************************************************/
//In the Control Panel
void
Close( Boolean IsOn )
{
long result;
CommonInfo *Info;
//Get address of globals struct from init
err = Gestalt( kSignature, &result );
if ( err == noErr )
{
Info = (GlobalsType *) result;
Info->On = IsOn; //Reset OnOff Boolean
( * (*Info).ResetINIT) (); //Jump to INIT
}
}
If it is possible for an error to occur that prevents the extension
from resetting itself the ResetFunction should return an error code
and the control panel should display an alert indicating the problem.
Two additional methods are sometimes used to accomplish communication
between an extension and a control panel:
The first of these is to write a driver that is installed by the
extension. The driver holds global variables and will return the
address of the block of memory holding these variables in response to
i/o, status, or control calls to the driver. Sample code showing how
to do this is available in a package called driver-22 written by Pete
Resnick to be found at:
ftp://sumex-aim.stanford.edu/info-mac/dev/src/driver-22-c.hqx.gz
The second additional method is to use the PPC toolbox for direct
communication. There is sample code demonstrating this at:
ftp://ftp.apple.com/dts/mac/sc/7.0.samples/init-cdev.hqx.
--
[9] How do I capture keystrokes?
This is accomplished by writing a jGNEFilter function. jGNEFilter
functions are called from GetNextEvent and WaitNextEvent just before
those traps return to an application. They are passed a pointer to
the event record that will be returned to the application. In order
to capture keystrokes the jGNEFilter would simply check the what
field of the event record looking for keyboard events and would
extract the information from the message field if one were found.
The jGNEFilter mechanism is very powerful and is one way that
screensavers can be implemented. The filter would save the time of
any keyboard events and would compare the location of the mouse
against its previous location on null events. If the preset time had
elapsed during which no keyboard events or mouse movement had
occurred then the screen saver would activate. A more complete
discussion of the jGNEFilter is in the next section.
If you are thinking of patching WaitNextEvent or PostEvent in order
to capture keystrokes or other events, don't. Use a jGNEFilter
instead. It's easier, it's compatible. It's even documented. See
the Tech Note 'GetNextEvent; Blinking Apple Menu' (#85).
ftp://ftp.apple.com/dts/mac/tn/toolbox.tb/tb-11-getnextevent.hqx
--
Brian Stern :-{)}
Toolbox commando and Menu bard
Jaeger@fquest.com
---------------------------
>From Jaeger@fquest.com (Brian Stern)
Subject: INIT Writing FAQ [2-3]
Date: 28 Oct 1994 00:42:44 GMT
Organization: The University of Texas at Austin, Austin, Texas
--
[10] How can my extension get time periodically?
Installing a jGNEFilter is one method of obtaining periodic time.
Since the jGNEFilter mechanism is dependent on the event processing
mechanism, one problem is that no events may be posted if the mouse
is held down for an extended time.
If your INIT only needs to get time every once in a while then I
recommend that it only do its thing on null events. On other events
it should just return. This will have the least impact on the
machine's performance.
Remember that your jGNEFilter will be called for EVERY event on the
machine. Do not do a lot of processing on every event or you will be
slowing down the machine needlessly. Another way to reduce the
frequency of your extension's processing is to use a simple timer,
based on TickCount(). In this way your processing is only done, say,
every 30 or 60 ticks, on null events of course.
Sample code demonstrating jGNEFilters can be found in a package
called jGNE Helper by Pete Gontier in the alt.sources.mac archive at:
ftp://ftpbio.bgsu.edu/ftp/pub/alt.sources.mac/vol-
01/jgnehelper.cpt.hqx.
Another sample in MPW assembler is at
ftp://ftp.apple.com/dts/mac/sc/snippets/toolbox/jgnefilter.hqx.
Here's another example that works in Think C:
static ProcPtr gOldGNEFilter;
/****InstallFilter***********************************************/
//Run this at INIT time
void
InstallGNEFilter (void)
{
/*Save the ProcPtr to the previous jGNEFilter and insert ours*/
gOldGNEFilter = JGNEFilter;
JGNEFilter = (ProcPtr) StripAddress( FilterProc );
}
/****FilterProc**************************************************/
void
FilterProc(void)
{
EventRecord *theEvent;
long SaveD0;
theEvent = GetA1(); //Move the eventPtr to a variable
SaveD0 = GetD0(); //Preserve D0
SetUpA4();
switch ( (*theEvent).what ) {
case nullEvent:
//Do our thing
break;
case keyDown:
//Do something else
break;
}
//Execute the previous jGNEFilter
SetA1( theEvent ); //Restore A1 for the next jGNEFiler
SetD0( SaveD0); //Restore D0
SetA0( gOldGNEFilter ); //Put next jGNEFilter in A0
RestoreA4();
asm{
Unlk A6
Move.W D0, 4(A7) ;Set Function result on the stack
JMP (A0) ;Jump to the next jGNEFilter
}
}
Since a jGNEFilter has access to the actual event record that will be
returned to the application, the filter can alter the event. The
most common thing to do is to 'cancel' an event by changing it to a
null event (Ex. theEvent->what = nullEvent). In this case it should
also set the value in register D0 to False, or zero.
Here are some additional methods for an extension to get time
periodically:
If your extension needs more frequent or regular time then can be
provided by a jGNEFilter then you can install a VBL task or a time
manager task. Since these run at interrupt time they cannot do
anything that could move or purge memory. Other methods include
patching a trap that is called frequently, like SetPort.
A faceless Notification Manager request is another method to get
time. This is a request that has all the fields in the notification
record set to NULL except the nmResp field that holds the address of
your routine to be executed. Your notification response routine will
be called soon and will be able to move memory. If necessary the
routine can reinstall itself. This technique is useful for tasks
that need to be executed once or intermittently. For those tasks
that need to be executed regularly use one of the other techniques.
You could of course have a faceless NM request that is installed by a
VBL task or a time manager task.
Use of a faceless background application in concert with an extension
is yet another method to get time. The fba would do its work on its
null events.
--
[11] How should an INIT manage memory?
In general, at INIT time extensions will want to allocate memory in
the system heap. If you are allocating pointers or handles, use the
SYS variants, like NewHandleSys() and NewPtrSys(). It is a common
error to forget this and then to wonder why the INIT crashes. If you
call NewHandle at INIT time, the handle will be allocated in the
temporary heap allocated for your extension. If your INIT attempts
to use it after INIT time the temporary heap will be long gone, along
with any handles or pointers that had been allocated in it. Any
attempt to use handles or pointers that no longer exist are
predictably unpredictable :-)
NewHandle and NewPtr will allocate their memory blocks in the system
heap if the zone has been set to the system heap, as shown in the
next paragraph.
If you need to read in resources you can ensure that they go into the
system heap with something like the following code:
THz saveZone = GetZone();
SetZone( SystemZone() );
//read in resources
SetZone( saveZone );
You will of course need to detach the resources if they need to
remain in memory after your extension exits. The resource file
containing your extension will be closed when your extension exits.
If you need to read resources into memory after INIT time you need to
decide which heap they should go into, either the application heap or
the system heap. It's a bit hard to make a specific recommendation
on this but if the resource is something that the application is
expecting to be read in then it should go into the application heap.
This would include things like WIND resources in a trap patch to
GetNewWindow(). The problem of course is that the application heap
may not have enough room. However, if the resources are private to
the extension then they should go into the system heap.
It should go without saying that you should always check the error
codes on memory allocating calls and resource manager calls. If your
extension is doing something in response to a user action, say making
a network connection, then it is appropriate to report such errors.
In many cases however, your extension will simply do nothing in the
case of out of memory errors or missing resource errors. It is best
to attempt to allocate all of these things at INIT time and if
unsuccessful to bail out then.
As mentioned above, MoveHHi doesn't work in the system heap. If you
intend to allocate a handle that will remain locked for extended
periods, then call ResrvMem before allocating and locking the handle.
This will place the handle low in the system heap and help to prevent
heap fragmentation.
Many toolbox calls are documented as not moving or purging memory and
as being safe to call at interrupt time. If you are patching one of
these traps then you must preserve this property. You are guaranteed
to cause other software to crash if you don't, and your users will
hate you (once they figure out that it's you). Be aware that the
only memory manager routine safe to call under these circumstances is
BlockMove. Also be aware that it is unsafe to access an unlocked
handle at interrupt time. It is possible that the memory manager is
in the midst of moving it from one place to another in the heap, and
the master pointer may not be updated yet.
--
[12] How do I get my INIT to turn itself off?
An extension might want to turn itself off at INIT time based on its
preferences setting, or based on a key being pressed or the mouse
button being pressed, or due to an error during initialization.
Extensions usually show an icon with a red X through it in this case.
An extension might also want to turn itself off temporarily after
INIT time in response to its Control Panel. For instance GateKeeper
has an on/off switch that turns off virus checking for a set time.
The strategy for temporarily turning off an extension is simply to
set a global flag and to check it from within the trap patches or
other parts of the extension. If the flag is off then the trap patch
simply executes the previous trap. It is generally unsafe to unpatch
or patch traps after INIT time from an extension. The reason for
this is that if another extension patches the same trap after you
have, then it will be jumping to your patch when it has completed its
work. If you have removed your patch then this calling chain will be
disrupted and bad things will happen. Also, the Finder patches
various traps when it loads, which is after INIT time. Disrupting
those patches would be a very bad thing.
If an extension determines at INIT time that it isn't going to stay
around then it shouldn't call DetachResource on itself. It's best
that your extension determine that anything it's dependent on, such
as resources, specific system Managers, and sufficient memory, are
present *before* it starts to patch traps and install drivers,
jGNEFilters and so on. It would be a very bad idea for an extension
to not detach itself after it had already patched a trap if the trap
patch resided in the extension.
Many extensions use a particular key press as a signal to indicate
that the user wants them not to run. Of course the system uses the
shift key as a signal not to turn on any extensions so you can't use
that. Some extensions use the option or command keys for this
purpose. The problem with using those keys is that every time I
rebuild the desktop those extensions are needlessly inactivated. I
recommend that the space bar be used for this purpose. Here's some
sample code:
Boolean
SpaceBarIsDown(void)
{
KeyMap theKeys;
GetKeys( theKeys );
if ( theKeys[1] & 0x00000200 )//Check for spacebar
return TRUE;
else
return FALSE;
}
--
[13] How do I get my INIT to show it's icon like all the other cool
inits do?
This is easy. There is code available that does this for you. Get a
package written by Jim Walker called ShowIcon7 at:
ftp://mac.archive.umich.edu/mac/development/source/showicon7.sit.hqx
You use it essentially as a plug-in. Just pass in the icon's
resource ID and it does everything for you. It also shows how to set
up an A5 world in an extension. You might also take a look at Dair
Grant's Extension shell package. This one shows how to do animated
icons.
If your extension decides that it can't install itself then it passes
the resource ID of an icon that has a red X through it to the
showicon7 code resource.
Some extensions include the ShowIcon code within their own code
resources. This code is only about 1K but it seems pointless to me
for this code to sit in the system heap when it doesn't have to be.
Use it as a plug-in for your extensions.
--
[14] How do I show a dialog from my INIT?
First of all, I hate windows of any kind during the startup process.
If all you want to do is show an alert then use the Notification
Manager. Your alert will show up when the Finder starts but the user
will see it and will get whatever message you need to send.
The problem I have with windows at INIT time is that they slow down
this process and require user interactivity in a process that
shouldn't do so. Consider the computer that is on 24 hours a day
doing something important unattended. The power goes off and when it
comes back on the machine reboots. The user returns several hours
later to find that the machine is still in the middle of its startup
because your alert is waiting for a response. Consider also the
hapless INIT writer who has to reboot his machine 20 times a day.
Your INIT will not last long on my, um, his machine.
One additional annoyance is that you need to call InitWindows to show
your window and this erases all the nice INIT icons on the screen. I
hate that.
Here are a few possible alternatives.
* Play a sound or use the Speech Manager to communicate the
information.
* Show a different icon during startup to indicate an error. An icon
with a red X through it is one way to do this. You could also use
animated icons.
* If you must put up an alert then use a timer so that the alert goes
away by itself, even if the OK button isn't clicked.
* If you need to interact with the user to get some information, say
a password for a network connection, then do this once and save the
results in a preferences file. Provide a Control Panel to change the
information. Think of Control Panels as the interface for
extensions.
* Store descriptions of any errors that occur in a preferences file.
Have the Control Panel display this information. Remember to clear
this information on each restart and to indicate to the user by sound
or icon that an error has occurred.
* If you need to communicate error information to the user after INIT
time then you should definitely use the Notification Manager. For
example, MacSLIP uses the NM to show an alert indicating that the
carrier has been lost.
If you still want to show a dialog at INIT time then you need to set
up an A5 world first. The ShowIcon7 code mentioned above shows how
to do this. Also see the Tech Note 'Stand-Alone Code' (#256) for an
explanation and sample code for this and 'Giving the (Desk)Hook to
INITs' (247) discusses a bug that can appear when showing windows
from extensions.
ftp://ftp.apple.com/dts/mac/tn/operating.system.os/os-02-deskhook-
and-init.hqx
If you do use the Notification Manager from an extension to indicate
that the extension couldn't load you should use a self-disposing
Notification request. There are several strategies for doing this.
I have some code samples for this that will be (have been?) posted to
alt.sources.mac soon.
--
[15] How do I maintain compatibility with future systems?
This is tough, and the short answer is that you probably don't.
You'll notice that Apple comes out with new versions of its
extensions with each revision of the system. Apple's extensions also
eventually disappear as their functionality is rolled into the
system. In all likelihood you'll have to come out with new versions
of your extensions as new versions of the system come out as well.
Having said all that, there are things you can do to minimize this
problem. Here are a few suggestions:
* Minimize your reliance on undocumented features of the system.
* Minimize your reliance on low memory globals. Use the Universal
Header access 'functions' for accessing the low memory globals if
necessary.
* Use system features like Gestalt, the Process Manager, and the
Notification Manager to get information about the system, and to
communicate with the user.
* Try to patch as few traps as possible and use non-patching methods
whenever possible (e.g., use a jGNEFilter instead of patching
WaitNextEvent; the filter is more likely to remain compatible than
your patch).
* Don't use self-modifying code. Self-modifying code changes the
instructions from what they were compiled as, to something else, at
run-time. The classic example is to change the address in a JMP
instruction at run-time so that it jumps to the address of the
previous trap. This may seem faster than using a global variable but
it is only slightly faster. It is harder to write, debug, and
maintain self-modifying code, and it is definitely more likely to
break with new system releases. If you do use self-modifying code,
remember to flush the cache. See the tech note 'Cache As Cache Can'
(#261) for more information on that subject.
* Use the Universal Headers for writing your extensions. This will
help to ease the transition when it comes.
--
[16] Any tips for INIT writing?
You may not want your INIT to actually do anything until after INIT
time. You can find the end of INIT time if you have a jGNEFilter
installed when the first null event occurs. The Notification Manager
doesn't usually start processing requests until INIT time is over so
posting a faceless notification request is another method to find the
end of INIT time (probably the best if you don't need a jGNEFilter
for something else). You can also patch Launch to find the end of
INIT time but this is trickier.
Unfortunately some extension writers do put up windows during INIT
time. Because of this it's possible that events will occur before
INIT time is over. To fail-safe the above approaches you also need
to check for the presence of the Process Manager with a Gestalt call.
The Process Manager isn't available until after INIT time. If
Gestalt reports that the Process Manager is not available then you
need to reinstall your NM request, or simply wait for another event
to be reported to your jGNEFilter when the Process Manager is
available.
Here are some utility routines that can reduce the need for 68K
assembler in your extensions:
pascal void SetA0( void* ) = { 0x205F };
pascal void SetA1( void* ) = { 0x225F };
void * GetA0( void ) = { 0x2008 };
void * GetA7( void ) = { 0x200F };
- -------------------------------------------------------------------
Trap Patches:
--
[17] What exactly is a trap patch?
A trap patch is a method for changing the functionality of a trap.
The addresses of all the traps are maintained in the two trap
dispatch tables. By using the routine NSetTrapAddress and friends
you can change the address of a particular trap to code that you
provide. When this is done at INIT time, all calls to the patched
trap from all applications will go to your code, which in most cases
will do something and then call through the existing trap in the
ROMs. Be warned that the Finder patches some traps when it starts up
in a way that prevents previously-installed patches from executing.
I recommend that you read the descriptions of the trap dispatch
mechanism in the 'Using Assembly Language' chapters in IM I and IV
and also in the 'Trap Manager' chapter in NIM Operating System
Utilities.
Traps come in several types based on their parameter passing
conventions. Most toolbox traps use pascal calling conventions,
which means that all parameters are passed on the stack and the
return value, if any, is placed on the stack.
Some traps use register-based calling conventions. In these traps
the parameters are passed in registers and the return value is
returned in a register, usually D0. For example all the Memory
Manager traps are register-based and the File Manager traps are also
register-based.
Some traps are selector-based. There are only so many spots in the
trap-dispatch tables. In order to preserve space in these tables
selector-based traps have been developed. In these traps a single
trap serves as the front end for a number of system routines. The
parameters of these traps are passed in the usual manner, either on
the stack or in registers, and a selector is also passed, usually in
a register. When the trap is called it checks the selector and then
dispatches to the appropriate routine. Patching each of these types
of traps involves different mechanisms. We'll look at samples of
each one.
Patching traps on the PowerMac is a bit different than on the 68K
Macs. Most of the discussion here is aimed at patching traps on the
68K Macs. Hopefully I'll learn some more about this subject soon and
there will be some better info here on patching traps on the
PowerMac.
--
[18] What's the difference between a head patch and a tail patch?
It is most common to add some functionality to a trap when patching
it rather than just replacing the existing trap. For instance I've
written an extension that speaks the text in alerts by using the
Speech Manager. This works by patching Alert and friends. When
Alert is called the patch gets the text that appears in the alert and
passes it to the Speech Manager. The patch then calls the existing
Alert trap that is in the ROMs. A patch that works in this way is
called a head patch; it does its business and then it calls the
previous trap.
A tail patch is a bit different. A virus-checking program might want
to patch GetResource and then examine the resource that was read in
to see if it contains a virus. In order to do this the patch must
first call the existing trap and then do its processing, and finally
return to the application. This is a tail patch because some
processing occurs after the existing trap is called. In order for a
patch to be a head patch you must use a jmp instruction to jump to
the previous trap. If you use a jsr or a C function pointer to jump
to the previous trap you have a tail patch.
The reason that this head and tail patch business has been so
important in the past is because of an Apple invention called the
come-from patch. Patches were invented, of course, so that Apple
could fix bugs in the ROMs and could update the routines in the ROMs
with software. This is why you can run system 7 on a Mac Plus, whose
ROMs are obviously missing most of the additions made to the toolbox
in recent years.
Certain ROM routines are particularly large so it is inconvenient to
patch them if they have bugs in them. To get around this problem the
Apple programmers searched for smaller routines that are called from
the large buggy routines and placed patches in the smaller routines.
These patches check the return address on the stack. If it is the
address of the buggy routine then a fix is applied. If not then they
just go on as usual. The patches to these smaller routines are known
as come-from patches. If you tail patch one of these and then call
the existing come-from patch, the return address on the stack will be
in your patch and not the buggy routine that called you. In this
case the come-from patch will not apply its fix and your system will
crash.
The good news is that as of system 7 it is safe to apply tail
patches. The come-from patches still exist in system software, but
NGetTrapAddress has been modified to return an address that is safe
to use when applying tail-patches. However, if you wish your
extension to run in System 6 then tail-patches are not allowed. This
is documented in the Trap Manager chapter in NIM: OS Utilities.
If you absolutely positively need a tail patch in System 6 then the
following logic may apply: (Just don't tell anyone that I told you
this :-) Apple is not releasing any new versions of System 6 so no
new come-from patches will be forthcoming for System 6. If you do
careful testing of the traps you wish to tail-patch you will probably
be OK. In general traps not called from the ROMs, like Alert and
MenuKey, will not contain come-from patches.
One final thing: In system 7 it is safe to apply tail-patches to all
traps except FrontWindow.
--
[19] How do I patch a trap?
Here is some sample code for a head patch of Alert, a stack-based
trap:
TrapPtr gOldAlertTrapAddress;
/****InstallPatch***************************************************/
void
InstallPatch (void)
{
gOldAlertTrapAddress = GetToolTrapAddress( _Alert );
SetToolTrapAddress( (long) AlertPatch, _Alert );
}
/****AlertPatch***************************************************/
pascal void
AlertPatch( short alertID, ProcPtr filterProcPtr )
{
SetUpA4();
MyAlert( alertID) ; //Do our thing
//store the correct alert addr
//in A0 while we can still access globals via A4
asm { move.l gOldAlertTrapAddress, A0 }
RestoreA4();
asm {
unlk A6 //match the link generated by C
jmp (A0) //jump to _Alert
}
}
There are a number of details to note here. This patch is of course
part of a code resource that is loaded at INIT time and detached as
described in an earlier section. The routine InstallPatch must be
called at INIT time.
The routines GetToolTrapAddress and SetToolTrapAddress allow you to
get and set the addresses of Tool Traps. The similar routines
GetOSTrapAddress and SetOSTrapAddress allow you to manipulate the
addresses of OS traps. The routines NGetTrapAddress and
NSetTrapAddress allow you to manipulate the addresses of either,
although they call glue code. I recommend that you use the
GetXTrapAddress and SetXTrapAddress calls. There are two obsolete
calls: GetTrapAddress and SetTrapAddress. Don't use them.
The prototype for this patch is declared as 'pascal void' while the
prototype for Alert is 'pascal short'. Because this is a head patch
it will not be returning a result; the result will be returned from
the real Alert trap. The pascal keyword is used to indicate pascal
calling conventions. It is not strictly required in all cases but
does no harm.
The Think C routines SetUpA4 and RestoreA4 are called to allow access
to global variables by A4 addressing. In this case
gOldAlertTrapAddress is the only global variable we are addressing,
unless any are used inside MyAlert. Note that this variable is moved
to A0 while access to global variables is still available. In some
cases one might move a global variable to a local variable, which
doesn't rely on A4 addressing. A4 could then be restored and the old
trap address could be loaded into A0 later in the code.
Because there is a parameter list the compiler generates a Link A6
instruction at the start of this function. In order to restore the
stack a matching Unlk A6 must be placed at the end of the function.
Since we are exiting by the jmp (A0) we must insert the Unlk A6
ourselves. The compiler does generate an Unlk A6 and an RTS at the
end of this function, but they will never be executed. The presence
of the Link A6 instruction is dependent on the particular compiler
you use and on its rules for generating a stack frame. It is a good
idea to disassemble the code for your trap patches to see whether a
stack frame has been generated in order to determine if you need to
insert the Unlk A6 instruction. If you don't match the Link A6 with
an Unlk A6 the stack will be screwed up.
It is essential that the stack look exactly the same on exit from a
head patch as it does on entry. If not you will surely crash. (If
you had good reason you could modify the value of a parameter on the
stack, but that's another story.) This patch saves and restores A4
but does modify A0 and A1 (SetUpA4 uses A1). In general, with head
patches of stack-based traps you can modify A0, A1, D0, D1, and D2,
but not any other registers. You may need to look at the
disassembled code to be sure that all your registers are properly
saved and restored.
The design of the patch as shown here, with the patch code calling a
separate function to perform the actual functionality of the patch is
a good design to follow with all but the simplest of patches.
You might think that you need to call StripAddress on the address of
the patch routine before passing this address to SetToolTrapAddress.
This is not necessary unless the address is actually a handle. If
you were to load a code resource and pass its entry point to
SetToolTrapAddress then it would need to be stripped.
--
Brian Stern :-{)}
Toolbox commando and Menu bard
Jaeger@fquest.com
---------------------------
>From Jaeger@fquest.com (Brian Stern)
Subject: INIT Writing FAQ [3-3]
Date: 28 Oct 1994 00:44:27 GMT
Organization: The University of Texas at Austin, Austin, Texas
--
[20] How do I patch a register-based trap?
Here is the code for a sample register-based trap patch:
TrapPtr gMountVolAddress;
/****InstallPatch**************************************************/
void
InstallPatch(void)
{
gMountVolAddress = GetOSTrapAddress( _MountVol );
SetOSTrapAddress( (long) MountVolPatch, _MountVol );
}
/****MountVolPatch**************************************************
This is a register-based trap that has A0 set to point to its
parameter
block on entry. The prototype for MountVol is:
pascal OSErr PBMountVol( ParmBlkPtr paramBlock )
This patch beeps when a floppy or CD-ROM is inserted or when a
harddrive is mounted by the Finder.
*******************************************************************/
pascal void
MountVolPatch(void)
{
//Save some registers
//Save A0 since it's trashed by SetUpA4
//D1 contains the trap word
asm { movem.l a0/d0-d1, -(sp) }
SetUpA4(); //Allow access to global variables
SysBeep( 5 ); //The guts of our head patch
//store the correct MountVol addr
//in A1 while we can still access globals via A4
asm { move.l gMountVolAddress, A1 }
RestoreA4(); //Restore previous value in A4
asm { //Restore the registers
movem.l (sp)+, a0/d0-d1
jmp (A1) //jump to _MountVol
}
}
This head patch is similar in structure to the patch to Alert with a
few differences. The prototype uses no parameters and has no return
value. The single parameter is passed through A0. This patch doesn't
do anything with this value but it could be moved to a local variable
and then used to reference the fields in the parameter block if
desired. Access to global variables is by the same A4 mechanism as
in the Alert patch. Note that _MountVol is an OS trap so
GetOSTrapAddress and SetOSTrapAddress are used to set up the patch.
Since A0 is used to pass the parameter to this trap we jump to the
real _MountVol trap through A1.
Obviously A0 must be saved and restored in this patch. OS traps
expect to find the trap word in D1 so it must be saved and restored
as well. Three registers, A0, D0, and D1, are saved onto the stack
with the movem instruction, and restored at the end of the patch.
Think C doesn't generate a 'Link A6' at the start of this function
because there are no parameters and no local variables. Because of
this no 'Unlk A6' is needed at the end of the function.
--
[21] Can you show me an example tail patch?
Here is another example of a patch to a register-based trap. This
sample is a tail patch and is dependent on the CodeWarrior
environment. Because CW allows you to specify that parameters are
passed in registers this trap patch requires no assembly.
extern pascal OSErr (*Old_MountVol)( ParmBlkPtr pb : __A0 ) : __D0;
pascal OSErr My_MountVol( ParmBlkPtr pb : __A0 ) : __D0
{
OSErr err;
long saveA4 = SetCurrentA4();
err = Old_MountVol( pb );
DoSomthingFunc();
SetA4( saveA4 );
return err;
}
--
[22] How do I patch a selector-based trap?
Here is a sample patch to PrGlue. This trap is the front end for all
the Printing Manager routines. Its selector is pushed on the stack
typedef struct
{
long Selector;
THPrint hPrint;
} PrJobDialogStack;
TrapPtr PrGlueAddress;
/****InstallPatch****************************************************
/
void
InstallPatch(void)
{
PrGlueAddress = GetToolTrapAddress( _PrGlue );
SetToolTrapAddress( (long) PrGluePatch, _PrGlue );
}
/****PrGluePatch****************************************************
This is a stack-based trap with a long word selector also pushed
onto the stack. On entry the selector is at 4(A7). The return
address is at 0(A7). After the 'Link A6' the selector is at 12(A7).
*******************************************************************/
#define kSelectorOffset 12
#define kPrJobDialogSelector 0x32040488
pascal void
PrGluePatch(void)
{
PrJobDialogStack *StackPtr;
//Get address of the stack frame
//and save it in a local variable
asm {
lea kSelectorOffset(A7), A0
move.l A0, StackPtr
}
SetUpA4(); //Allow access to global variables
//Check the selector
if ( StackPtr->Selector == kPrJobDialogSelector )
{
SysBeep( 5 );
//Pass hPrint to our function to do something
DoSomethingFunc( StackPtr->hPrint );
}
//Store the correct PrGlue addr
//in A0 while can still access globals via A4
asm { move.l PrGlueAddress, A0 }
RestoreA4(); //Restore previous value in A4
asm {
unlk A6 //match C's Link A6
jmp (A0) //jump to _PrGlue
}
}
In order to access the selector and the parameters for PrGlue we use
a pointer to a struct. Once the pointer is initialized correctly we
can access the selector and any parameters from C easily.
According to NIM: PPC System Software it is not safe to patch
selector-based traps with PPC native code. All patches of selector-
based traps on the PowerMac should be written in 68K code.
--
[23] How do I patch a trap on the PPC?
See NIM 'PowerPC System Software' for a more complete discussion.
There is also a new book by Tom Thomson called 'Power Macintosh
Programming Starter Kit' that has examples of how to patch traps on
the PowerMac.
Patching traps on the PowerMac is similar to patching on the 68K
architecture. Of course you must generate a UniversalProcPtr for
each of your patches in the system heap, and these are then passed to
the SetXTrapAddress routines. Since code fragments have their own
globals the use of A4 or A5-based mechanisms for accessing global
variables isn't needed. In order to call the previous trap you need
to call CallUniversalProc or CallOSTrapUniversalProc and return its
result from your patch. As a result all patches on the PowerMac are
tail patches.
You may find an application called 'Traps Check' useful. This app
supplies a report about all the traps on a Powermac, indicating
whether each trap is emulated or native. Another way to do this is
to drop into MacsBug and disassemble from the address of the trap
you're interested in (e.g., 'il CopyBits' ). For traps that are
native you'll see a routine descriptor that begins with the
MixedModeMagic trap (AAFE). This of course won't tell you if the trap
has been patched. You can identify a patch by whether it's in RAM or
ROM, from its address. Determining whether a patched trap is PPC
native or not may take some additioinal sleuthing. You can find Traps
Check at: ftp://sumex-aim.stanford.edu/info-mac/dev/traps-check-
10.hqx
Here is a sample PowerMac trap patch for GetResource:
UniversalProcPtr gGetResourceUPP;
UniversalProcPtr gGetResourcePatchUPP;
/****InstallPatch**************************************************/
void
InstallPatch(void)
{
gGetResourceUPP = GetToolTrapAddress( _GetResource );
gGetResourcePatchUPP =
NewRoutineDescriptor( (ProcPtr) GetResourcePatch,
kPascalStackBased, GetCurrentISA() );
SetToolTrapAddress( gGetResourcePatchUPP, _GetResource );
}
/****GetResourcePatch*********************************************/
Handle
GetResourcePatch( ResType theType, short theID )
{
Handle result;
//We don't need no 'DUMB' resources
if ( theType == 'DUMB' )
result = NULL;
else
result = (Handle) CallUniversalProc( gGetResourceUPP,
kGetResourceProcInfo, theType, theID );
return result;
}
--
[24] Can I write a fat trap?
//Under construction
--
[25] Tips?
If your patch isn't called you may have guessed wrong on whether it's
a ToolTrap or an OSTrap. The high bit of the second byte of the trap
word is set for ToolTraps. The following function can be used to get
the correct trap address for both ToolTraps and OSTraps.
pascal void * GetCurrentTrapAddress( unsigned short trapWord )
{
if ( trapWord & 0x0800 )
return GetToolTrapAddress ( trapWord & 0x07FF );
else
return GetOSTrapAddress ( trapWord & 0x07FF );
}
If the machine crashes after leaving your patch you have probably
munged the stack or not saved and restored all the registers that you
must.
The Finder patches a number of traps when it loads in a way that
prevents earlier trap patches from functioning. If your patch
doesn't appear to be called it may be one of these patches.
--
[26] What other sources of information are available?
Knaster 'How to Write Macintosh Software'
Knaster and Rollin, 'Macintosh Programming Secrets'. These books on
Mac programming has some excellent info on trap patching.
Tom Thomson 'Power Macintosh Programming Starter Kit' This book has
some example code for writing trap patches and extensions on the
PowerMac.
The Extension Shell package at:
ftp://sumex-aim.stanford.edu/info-mac/dev/src/extension-shell-13.hqx
Dair's email address has changed to: dair.grant@ucl.ac.uk.
Usenet Macintosh Programmers Guide
ftp://sumex-aim.stanford.edu/info-mac/dev/info/usenet-mac-prog-guide-
msw.hqx
All of the Apple Tech Notes have been made available on Apple's web
server: http://www.info.apple.com/dev/technotes/Main.html
--
Brian Stern :-{)}
Toolbox commando and Menu bard
Jaeger@fquest.com
---------------------------
>From shawnl@andyne.on.ca (Dave Charlesworth)
Subject: Linking 68k object files to PPC program
Date: Thu, 27 Oct 1994 19:26:03 GMT
Organization: Andyne Computing
I want to link some third party code to a PowerPC program. Can someone
point me to documentation on how to make this work?
I don't have source for the third party stuff. I'm using MPW (ETO 15)
cross- platform tools (PPCLink, PPCC), and have the Inside Mac volume
"PowerPC System Software". I haven't been able to find anything in it
or in the ETO documentation, but it must be somewhere!
Thanks.
Shawn Leclaire
+++++++++++++++++++++++++++
>From zellers@pokey.basilsoft.com (Steve Zellers)
Date: Fri, 28 Oct 1994 20:52:49 -0800
Organization: BasilSoft, Inc.
In article <CyCJBF.Ms4@andyne.on.ca>, shawnl@andyne.on.ca (Dave
Charlesworth) wrote:
> I want to link some third party code to a PowerPC program. Can someone
> point me to documentation on how to make this work?
Assuming you mean that the third party code is 68k, you can't. You'll
have to write a stub code resource that re-exports all the symbols you
need through a paramblock as some sort using route descriptors.
--smz
+++++++++++++++++++++++++++
>From wdh@fresh.com (Bill Hofmann)
Date: Sat, 29 Oct 1994 18:27:36 GMT
Organization: Fresh Software
In article <CyCJBF.Ms4@andyne.on.ca>, shawnl@andyne.on.ca (Dave
Charlesworth) wrote:
> I want to link some third party code to a PowerPC program. Can someone
> point me to documentation on how to make this work?
>
> I don't have source for the third party stuff. I'm using MPW (ETO 15)
> cross- platform tools (PPCLink, PPCC), and have the Inside Mac volume
> "PowerPC System Software". I haven't been able to find anything in it
> or in the ETO documentation, but it must be somewhere!
>
Nope, not really. Maybe some of the MacTech articles have mentioned it.
But what you have to do is:
* find out which routines *you* call in the library
* write some 68k code that wraps the library in a way that you can
call it: either use a selector-based approach (ie, if message==1,
call function 1, etc) or make a routine that returns a table of
procptrs
* compile/link the wrapper with the library
* create proc infos and stub code to call your 68k wrapper in your
PowerPC program
* debug :->
Or, yell at the third party until they produce a PowerPC version (shared
library, or whatever).
-Bill
--
Bill Hofmann wdh@fresh.com
Fresh Software and Instructional Design voice: +1 510 524 0852
1640 San Pablo Ave #C, Berkeley CA 94702 USA fax: +1 510 524 0853
---------------------------
>From rjkmehta@bu.edu (Ravi Mehta)
Subject: Network Programming
Date: 19 Oct 1994 16:20:21 GMT
Organization: Boston University
I want to write some networkable software, but am completely new to network
programming. Besdies IM: Networking ( which I will pickup ) is there
anything else that would help? Will IM: Networking discuss programming
for BOTH AppleTalk and Ethernet? If not, what would be a good
source for learning how to write Ethernet and AppleTalk compatible software.
Thanks in advance.
Ravi J. K. Mehta
Terminal Sunset Software
+++++++++++++++++++++++++++
>From andym96@aol.com (AndyM96)
Date: 20 Oct 1994 01:13:05 -0400
Organization: America Online, Inc. (1-800-827-6364)
In article <383h05$a37@news.bu.edu>, rjkmehta@bu.edu (Ravi Mehta) writes:
<<
Will IM: Networking discuss programming
for BOTH AppleTalk and Ethernet? If not, what would be a good
source for learning how to write Ethernet and AppleTalk compatible
software.>>
yes, IM networking discusses how to do that. Also, a good book is
"Programming with AppleTalk" by Michael Peirce -code samples are in
Pascal, though, but it is a thorough and detailed description of how
AppleTalk protocols work & how to use 'em.
BTW, if you dicover a code sample how to write a requester-responder pair
using ATP in C, <<PLEASE>> e-mail me @ andym96@aol.com -I've been trying
to get this info for a couple of weeks now with no avail.
Andy
+++++++++++++++++++++++++++
>From ntuck@muddcs.cs.hmc.edu (Nathan D. Tuck)
Date: 20 Oct 1994 20:02:38 GMT
Organization: Harvey Mudd College, Claremont CA
>In article <383h05$a37@news.bu.edu>, rjkmehta@bu.edu (Ravi Mehta) writes:
>
>Will IM: Networking discuss programming
>for BOTH AppleTalk and Ethernet? If not, what would be a good
>source for learning how to write Ethernet and AppleTalk compatible
>software.>>
For both AppleTalk and Ethernet? AppleTalk is a software protocol while
Ethernet is the physical format that AppleTalk runs over. If you mean
LocalTalk and Ethernet, the two should be equivalent so far as ATP
API's are concerned. If you mean to run transparantly over different
protocol stacks such as ATP and IPX/SPX or TCP/IP, that is another
question entirely.
Nate
ntuck@hmc.edu
+++++++++++++++++++++++++++
>From Yorick_Ph*nix,MacTel_Iconex@metro.mactel.org (Yorick Ph*nix,MacTel_Iconex)
Date: 29 Oct 1994 02:48:38 GMT
Organization: MacTel Metro BBS, London, England.
Ravi
> I want to write some networkable software, but am completely new to
> network programming. Besdies IM: Networking ( which I will pickup )
> is there anything else that would help?
There is a very good book called something like Introduction to AppleTalk
Programming - I have a copy at the office and I learnt all my Network
Programming from it. It is possibly published by Addison-Wesley and is one in
a series where Scott Knaster is the Series Editor.
AppleTalk programming is what you should be doing (ATP, NBP, ADSP, PAP, etc)
whereas LocalTalk and EtherNet are the phsyical mediums over which the
network data travels - you shouldnt need to get involved at this level or
even know which phsyical medium your program is dealing with.
Yorick
- sent via an evaluation copy of BulkRate (unregistered).
--
****************************************************************************
MacTel Metro - Europes largest Mac specific BBS
The views expressed in this posting those of the individual author only.
Send mail to this user at either :-
INTERNET:User_Name@metro.mactel.org [use underline] between first
FIDONET:User.Name@f202.n254.z2.fidonet.org [use fullstop ] & last names
****************************************************************************
---------------------------
>From walkerj@math.scarolina.edu (James W. Walker)
Subject: Stuck in SyncWait again
Date: Sat, 15 Oct 1994 21:39:18 -0500
Organization: Dept. of Mathematics, Univ. of South Carolina
When an application freezes, dropping into MacsBug often reveals that it
is stuck in SyncWait. When that happens, typing es to MacsBug or using
force-quit does nothing. Is there any hope for someone with debugger
skills slightly below those of "Kon & Bal" to get the app out of SyncWait
and make it die a clean death, or should I just restart the Mac?
--
Jim Walker
+++++++++++++++++++++++++++
>From jonasw@lysator.liu.se (Jonas Wallden)
Date: 16 Oct 1994 09:57:15 GMT
Organization: (none)
walkerj@math.scarolina.edu (James W. Walker) writes:
>When an application freezes, dropping into MacsBug often reveals that it
>is stuck in SyncWait. When that happens, typing es to MacsBug or using
>force-quit does nothing. Is there any hope for someone with debugger
>skills slightly below those of "Kon & Bal" to get the app out of SyncWait
>and make it die a clean death, or should I just restart the Mac?
>--
> Jim Walker
The SyncWait loop waits for a parameter block error code to drop below +1
(which is the value used while the call is in progress), and as we all know
this error code is 0 (noErr) for a successful request and negative for errors.
So, look at the SyncWait code to see which word it tests (usually something
like 10(A0)) and set this word to an error code (e.g. FFD5 for fileNotFound)
and it will often get you out of the lock.
I've used it successfully in Mosaic several times where it seems to hang
when I abort a connection, and at other times when the computer won't
reboot after a crash.
BTW, I have a MacsBug dcmd which lists error strings from error codes.
This is great as it's rather difficult to use ObiWan at these times...
Can't remember if I got it from sumex or a Developer CD, though.
--
`.`. Jonas Wallden `.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.
`.`.`. Internet: jonasw@lysator.liu.se `.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.
`.`.`.`. AppleLink: sw1369 `.`.`.`.`.`.`.`.`.`.`.`.`.`.`.
+++++++++++++++++++++++++++
>From wysocki@netcom.com (Chris Wysocki)
Date: Sun, 16 Oct 1994 16:31:58 GMT
Organization: NETCOM On-line Communication Services (408 261-4700 guest)
In article <walkerj-1510942139180001@192.0.2.1>,
James W. Walker <walkerj@math.scarolina.edu> wrote:
>When an application freezes, dropping into MacsBug often reveals that it
>is stuck in SyncWait. When that happens, typing es to MacsBug or using
>force-quit does nothing. Is there any hope for someone with debugger
>skills slightly below those of "Kon & Bal" to get the app out of SyncWait
>and make it die a clean death, or should I just restart the Mac?
Here's a MacsBug dcmd that I wrote a few weeks ago that simply does a
KillIO for a specified driver. You might be able to use this when
you're stuck in _SyncWait to kill the pending request and get out
safely. Since it's so small, I've attached it below, along with the
source code to it; hope you find it useful.
Chris.
- ------
(This file must be converted with BinHex 4.0)
:$dYTE'a*6b"NBfeN,R0TG!"6594%8dP8)3#3"!`[!*!%r2T6593K!!-!!!`[FNa
KG3,r!*!$&[rr$3d)5fPXE%P2,Q1Gm9!"8)H!!"8BQJ#3!i!!N!3"@**J4()!N"3
%R!#3"2q3"&4&@&408&-J!3#UUh$bUUYlc3!!!D`!!!F8!!!"%3!!!`8KNZFl!*!
'P&84!!JFl(B)BP9k**AKrPcJ1V9Vp)Y)6-*K36-cDDB[,XlVjq(F(52TkHdlqe,
528kFPY3cj!m%XHl!BBHmiNQm1dk-[J53!+ZSdrTSIqk,mhTa[FiTXQ&$R%R#AZp
J%C'5-PeA5k21&&hTI(#%T@*rS!G1i4NCK)8cm@"R"EPI9L3pM+@6dTk5%FD1N3A
d$XA1E2eFqc+pj4*T[kc89#T`30$qQH9`rdJka4&Q8TZ(CNTR%"@FBEY*#SIZ2"h
9fMXDeZAACHmJpa[Df"Z%R"!,95(&3f,U3"Z(Ym@d21(%V@i%L*f5MGaVHQmS26m
&RBReV@XMPA-rAE+RSe"S$Z"F6FJ*%'1Q+$8VMjpUY##U5Kq`#Ni"b1-*-S$*bXK
4JLr#EMe#Ml!M[ailMaacd#PK!b98pT)")`1!&5$A8l)#j$1!VjF`XK,d-B*q"!"
hAB-N6-+1(#0--Q$N'%%6)`a2$JrX`!#kK`Pj*56[%r*'5$QilV!N)HGDH5U8kcF
Lb&L4`84EH%HC1bZRk(&VKIGF`EMUNr2F#JHhPG0X*U+rUDbBjVj2[X&4VrF8SS2
A*ZF@EMTVU`kmP"+LN`2,(EGcRR9#J*bU+BHVi'NV5![Y2"S`VMa-K(@qh8FA!Lq
16JRdZXI2ZVfRK0N&)HH@8mqa,+X,q+4Pk21`Qb52K'+bc$Lmq&!ClMVjk8jb`HH
#hBX#&YmPPpCU'c9E85Z`dFPE1i8TI4!NhHl*2`FqM)4`&399fDAbY[Sh3F6%8-H
SK,N@'Gb&6826Ca,"234$,5f'hVD6V`NjdeTbUN$2i!3Q9$Vq2#&5UbNL1m(6-*K
&ia[1`)a4FMe#PS"Eqa`jGJ[K@3lT1Y568mZrP"`T6`J!"L5-1Kj(D+#%lk1!M*(
c@6$IDUqi0&%EMKH@,Yi+aG2@Cp1-'*DKbU,9a[Jr2!"Ji"b'"JU0(d)J`@[`1HD
cBSl6K8APm6l&XrUED,q,m!51Rm')'amRXA(pfH1&(Y3GKq0S3FfYYM*c+4S'94V
!E%HRepbrjdYrZ63iRNjSP4jJ*BrK3-mD-c'"&)rK&$JLa)`l3NFJmIq'6pkA"8+
EZPaEhfjia3r*40R`V%CK9#Q@(TKaA4Q*2m25$dIHl[K#9"T-QQk$amFV[X6qXK5
MhGQ(BQ,)%e!DYb"@Y%m&VQ3ibQj5bR8HMY-5$h@AHcI,I@N9,MqQ`SI+fR,I`ET
QY'Mi)*[a#CTDdB5VJ@6i&,*DBN-4bI[8k9EIhN6H8,h,-DEC4pbZKaaErCmFC6!
TM+mHNY`jr-QLY,mfA$dNfHTrjeM&he@0%RV(lDZYSR3$l2diiU*iZUaC$GPqcGe
q(c-qSD@XPh&A8kPQ5Lr#&XFR`aVmJ2d&CcrI&'[jVUYeT3#VC*Am"`!0$3Y,D@a
X58mZE@&VC3&3Ki!!&4LD!*!$J!#3"!&BNQ!-d`#3%4B!!!H+!*!%rj!%9%9B9%e
38b!"!+UVH01UUhSa!!!"V!!!!NN!!!%K!!!"AA@DY)S!N!B0#"%!#"cXGJKLe6K
CXcV%MX[FG-ra@EM-Q*1JqQRRHDD'!FE8USiQY*ZBYf-N2EepCem''8Jp6U#@e$2
N$`3a!Z8mCMMKX0iG*`kj(F$6hQPp0(R#e8GeIJ%+eS4fkG!QqH5mj@Eb5J'&SF-
f2IHXLC)Rh(G9"qMC168fkZRVLD,5%1MFep-UPejSIKqSAS9"2M5KC&YdF44UJT2
VUSRD-6A0`HGUqL"IcAc*%fEiUN1YTKkBb+#`dhG'kSD9Um1'9DY$D@F3&EaqcNJ
+Krk4G&5rae5"XdH@`bNCiEMbFH@pN!!6BL%!f*2KHAX@[q2%BI(1MNACD0i4kc1
HBUp[A4ZT0(jFbCk13U%jJ(-e)5G!M*NbjfliU8B,SLT[(QS"!*!$8E@%YC*-rU"
2Qj68cKm-QZh*@Hk!6mM($"M#ERmSV%fbNSK()*!!!4()aB$ANqA0`C`L2mDq%%M
2eLET'H32JdlCBHJ*q'-5`fcNcf5`0QNL509S'S!F4J*CaSH!-cN1di%Z'!3j*!k
3!#rX3a'I0cPASHm1CIT!'jiDC`0a&JaMJV"p)3`br#L-*GSF$MkJ85JE+M30NM`
SQT5N4cihpZ@fe)A!!(N1%qB@U#40R4U[h%k'X9TPqiV&(`U!HPUqBl$idj%EqAh
KR22p)1G,GLI$HN"V6qrMmq#`GSR%%q53!-0mm$B3$8L%TL)R&m,q,"m"PZ,L,+N
9j`pk$6`qA9K&U@`S6$*k'1,PKca"cZX$SYaXS8Np-"!iIIf"h-dl&!DNCBHa,mX
%JeiI'Q6`TA1CQ@4IEH6,#)[LP9-6bZ,5VbShJ"`"H6U3!2[M,6C$f)Fbh"j5iqd
ib`DmlV2UfAi0!!C,D@aX58pH3*ha8!&3Ki!!&4LD!*!$J!#3"!&BNQ#bS3#3%!5
F!*!)rj!%FR0bBe*6483"!+UVGE5UUh[D!!!(@`#3"J3e!*!%6D`!N!Mf(#0%$L)
UV5%U359,L)ir2,PP8%TR&'k`ZDaG08a*8EM1j[X@-!H9V*B9TEeVY40LeBBHkik
d""f8``-#qHkTril9mECq)[ZJMDJqD&Y$,kRKF%G[EjmqVDQJ'YKb9*Epd-r)f80
lCrk#pNeprZ(hI,RIi`m5d[MlTja#6SFVp"EjQhp'Xk8C8Sh%T#R5bG+*dQ6T1'Q
L0&kUNXC*&9+j9#D95#l*'GV%TJEHbMfhqq+AGV%0+kLqM+A*&6S3@TZlTqd94eQ
Y5Q9qAqi6$AAN5K)GLM3PCk$b286IDY[X1"ak1(F6qXI4hi2qE[3V`$dSH"1[E&0
cpk*q#fMG+VM)li+(9F[9h(fja`1[jHjRlAY+cL$SQN-21e2e[YbpSBH,DPDY$(F
P+X!+!LYhI9I2@Q!%@%C$DG[qHS'd0C5kQR)r$(FP'clFP'4)a(K@8m,AYTNH"cX
)QL(!`!dl(PJ!-%L',3'Q"9BGHYMae[SZG0NpCF$c3`mI4Q*YVrDF#$3H[0G&hU*
AEM,`X("AafY9`lRE3ZIiEJeP,`YdGABfKi)YS@Mh@H3SUFUUIDSfS$+GEmTb`f4
8%4P56@Q3!(&Geh6bXPT9-lXbA'h4p9P%PD`fUmTQ5cTM$YN-8#L5iQX%5FCRD+U
TDiU0'f'Y*UZV2'jE%XM$M'`XaJdMN9@)UZeG*TJDLqYb2hBFSDQ-X8"+P`ffEXM
3BRdbGQ$F3KEK'C-e,PQbJ1Kd+)`e$%3Q5#c[B!Ef'0US5I'#PIQbQE,`QB!aj&)
eQdC'NU+-CkmPUUpSreQ1@!HVk"kZD@*c$arDij[mbF1jqSV3`fpR-M5RkI#K@M9
h+(41+$ZQ"cUjRcamk)6lb%0dK&r&a!cD[PA!,Dm8P3R&5"p9q(`B#pK2U,lr-VK
9l[&p(bi+A&"ml[0!+YjSQ([iX"p*`r3fjRijkN,FE)YTbX3-e90pD8e&prCk"h6
A@A2H2+TN%&k0m+TM2LTc$Q20'YU'frE2*S'IfP9,bFQX*$*F6ka8G0(#rHkZRe0
&6fhNSP8lY3V"@cGXT4,eL*9+3AQQ3H6DGRKp9f5RqRUQr2i,Be@X@'miX0hLRF5
QdJ0rIVH0(eU2r8-1jJk1c!@N9ZfUGjLd`%IPp8jibcf5@35bSCNTp2,3`h505#b
FmQK4(5@VmQNTSE`hh08cHFe1N9$ECIEF9%fhI%pIhm9F)kRNr,X8SZ%8203,6NJ
pZ6#`kZDhU(cH&R+'$PjpZ+HNSjNFd0Y*-aMk$c683Z2CTP"fKD1YH99ciZ3DR$#
@jQ6jqGpZDfjVDR#d03fr-)rm6@h3X$5IFAjpd3)keD%l"!0ZKC3'Tdipach6c-F
rkrrkm2dAm&rZ[Z#CjV*(LH+[R6Te`G43pMrG6jj3AXH&c-`qqm@6,J0LSRQBP"R
T1$#YkiQm9X6CHr)hmP8!N!2-eJ!!:
+++++++++++++++++++++++++++
>From h+@nada.kth.se (Jon W{tte)
Date: Sun, 16 Oct 1994 20:15:31 +0100
Organization: Royal Institute of Something or other
In article <walkerj-1510942139180001@192.0.2.1>,
walkerj@math.scarolina.edu (James W. Walker) wrote:
>When an application freezes, dropping into MacsBug often reveals that it
>is stuck in SyncWait. When that happens, typing es to MacsBug or using
>force-quit does nothing. Is there any hope for someone with debugger
>skills slightly below those of "Kon & Bal" to get the app out of SyncWait
>and make it die a clean death, or should I just restart the Mac?
Usually this means a SCSI request isn't being served (or an
Ethernet request, or a Serial Port request, or...) This is
usually caused because of buggy drivers (like early Applied
Engineering drivers, some CD-ROM and MO drivers and version 1.x
of the Digidesign card drivers)
When something hangs in _vSyncWait, it waits for the word at
(a0)+10 to go 0 or negative (this is ioResult in the parameter
block) One thing you can TRY is:
atba
sw a0+10 ffff
g
atc
es
This will make the app halt as soon as it gets to an A-trap (so
it won't just get stuck again) Then it fakes an interrupt
service routine that sets the result to -1 (an error code) Run
with this; and as soon as an A-trap is hit, clear breaks and
exit.
However, since this is a driver that got hosed, chances are
you'll run into the same problem an instant later, so it's
usually not terribly helpful.
There are also several conditions which can make this fail:
- If some idiot masked interrupts, that's the reason you're
waiting for an interrupt that's never serviced. Check with TD
and look at the Int= figure - should be 0. 7 is real bad.
- If this was because of a file manager request; the file
manager is now in a meeting for the rest of the day, which
means you earned just about nothing by breaking out.
- If the driver makes interesting assumptions about the return
value you use (ffff==-1 in this case) OR wants a completion
routine to be called, you're probably hosed anyway.
There should be a law only competent people can write drivers.
Unfortunately it seems to be the other way around with some
people "Hey, we've got this interesting hardware we can sell.
However, hiring someone expensive to write the drivers would
eat into our margin way too much. Isn't Joes 13-year-old kid
into computers? Have him whip something up and we'll give him a
Happy Meal."
Hardware without drivers is pretty useless.
Cheers,
/ h+
--
Jon Wätte (h+@nada.kth.se), Hagagatan 1, 113 48 Stockholm, Sweden
-- I don't fear death, it's dying that scares me.
+++++++++++++++++++++++++++
>From jumplong@aol.com (Jump Long)
Date: 17 Oct 1994 00:44:01 -0400
Organization: America Online, Inc. (1-800-827-6364)
In article <walkerj-1510942139180001@192.0.2.1>,
walkerj@math.scarolina.edu (James W. Walker) wrote:
>When an application freezes, dropping into MacsBug often reveals that it
>is stuck in SyncWait. When that happens, typing es to MacsBug or using
>force-quit does nothing. Is there any hope for someone with debugger
>skills slightly below those of "Kon & Bal" to get the app out of SyncWait
>and make it die a clean death, or should I just restart the Mac?
Here are a couple of paragraphs from the article "Asynchronous Routines on
the Macintosh" in develop issue #13 that explain deadlock conditions and
SyncWait:
- ----
Avoid SyncWait.
Does your Macintosh just sit there not responding to user events? Drop
into the debugger and take a look at the code that's executing. Does it
look like this?
MOVE.W $0010(A0),D0
BGT.S -$04,(PC)
That's SyncWait, the routine that synchronous calls sit in while waiting
for a request to complete. Register A0 points to the parameter block used
to make the call, offset $10 is the ioResult field of the parameter block,
and SyncWait is waiting for ioResult to be less than or equal to 0
(noErr).
The ioResult field is changed by code executing as a result of an
interrupt. If interrupts are disabled (because the synchronous call was
made at interrupt time) or if the synchronous call was made to a service
that's busy, you'll be in SyncWait forever. Take a look at the parameter
block and where it is in memory, and you'll probably be able to figure out
which synchronous call was made at interrupt time and which program made
it.
- ---
Deadlock is a state in which each of two or more processes is waiting for
one of the other processes to release some resource necessary for its
completion. The resource may be a file, a global variable, or even the
CPU. The process could, for example, be an application's main event loop
or a Time Manager task.
When deadlock occurs on the Macintosh, usually at least one of the
processes is executing as the result of an interrupt. VBL tasks, Time
Manager tasks, Deferred Task Manager tasks, completion routines, and
interrupt handlers can all interrupt an application's main thread of
execution. When the interrupted process is using a resource that the
interrupting process needs, the processes are deadlocked.
For example, suppose a Time Manager task periodically writes data to a
file by making a synchronous Write request, and an application reads the
data from its main event loop. Depending on the frequency of the task and
the activity level of the File Manager, the Time Manager task may often
write successfully. Inevitably, however, the Time Manager task will
interrupt the application's Read request and deadlock will occur.
Because the File Manager processes only one request at a time, any
subsequent requests must wait for the current request to complete. In this
case, the synchronous request made by the Time Manager task must wait for
the application's Read request to complete before its Write request will
be processed. Unfortunately, the File Manager must wait for the Time
Manager task to complete before it can resume execution. Each process is
now waiting for the other to complete, and they will continue to wait
forever.
Synchronous requests at interrupt time tend to produce deadlock, because
the call is queued for processing and then the CPU sits and spins, waiting
for an interrupt to occur, which signals that the request has been
completed. If interrupts are turned off, or if a previous pending request
can't finish because it's waiting to resume execution after the interrupt,
the CPU will wait patiently (and eternally) for the request to finish -
until you yank the power cord from the wall.
- ---
Read the rest of that article, it'll help you write code that doesn't end
up in SyncWait.
- Jim Luther
+++++++++++++++++++++++++++
>From walkerj@math.scarolina.edu (James W. Walker)
Date: Mon, 17 Oct 1994 23:41:46 -0500
Organization: Dept. of Mathematics, Univ. of South Carolina
In article <37sveh$t0t@newsbf01.news.aol.com>, jumplong@aol.com (Jump
Long) wrote:
> Read the rest of that article, it'll help you write code that doesn't end
> up in SyncWait.
I guess I didn't make it clear in my original post, but it's not *my* code
that gets stuck in SyncWait. It's usually Internet apps like Anarchie. I
was just wondering whether there was anything I could do when it happens,
other than restart, and this thread has given me some ideas. Gee, I can
hardly wait for the next freeze. :-)
--
Jim Walker
+++++++++++++++++++++++++++
>From bierman@caelab1.cae.wisc.edu (Peter Bierman)
Date: Tue, 18 Oct 1994 14:36:31 -0600
Organization: Happy Frogs, Inc.
In article <walkerj-1710942341460001@192.0.2.1>,
walkerj@math.scarolina.edu (James W. Walker) wrote:
> In article <37sveh$t0t@newsbf01.news.aol.com>, jumplong@aol.com (Jump
> Long) wrote:
>
> > Read the rest of that article, it'll help you write code that doesn't end
> > up in SyncWait.
>
> I guess I didn't make it clear in my original post, but it's not *my* code
> that gets stuck in SyncWait. It's usually Internet apps like Anarchie. I
> was just wondering whether there was anything I could do when it happens,
> other than restart, and this thread has given me some ideas. Gee, I can
> hardly wait for the next freeze. :-)
Well, all of the ideas are good and accurate, but here's an easy fix.
Do a step (oa-T) till Macsbug says "Will [not] branch". Then type:
pc=pc+2
g
That will jump you out of the loop. It's faster than "fixing" the loop
condition. Just note that what John said is true: it'll probobly happen
again withing a short time. Restart right away.
-Peter
--
Peter Bierman \ The Metropolis \ The most primitive part of the
bierman@caelab1.cae.wisc.edu\ (614)-846-1911 \ the brain concerns itself
\ 600MB Mac Files \ with the "Four F's":
"I've changed my mind, Hobbes.\ FirstClass GUI \ Feeding, Fighting, Fleeing,
people are scum." --Calvin \ Info-Mac CD-ROM \ and Reproduction.
+++++++++++++++++++++++++++
>From richardb@cocytus.demon.co.uk (Richard Buckle)
Date: Wed, 19 Oct 1994 06:37:42 GMT
Organization: none
In article <AAC73A63966886B32@klkmac003.nada.kth.se>,
h+@nada.kth.se (Jon W{tte) wrote:
>>When an application freezes, dropping into MacsBug often reveals that it
>>is stuck in SyncWait. When that happens, typing es to MacsBug or using
>>force-quit does nothing. Is there any hope for someone with debugger
>>skills slightly below those of "Kon & Bal" to get the app out of SyncWait
>>and make it die a clean death, or should I just restart the Mac?
To be honest you can often get away with stepping over the SyncWait test if
you restart *immediately* you regain control.
In MacsBug, do a T 40. This should pop you out of any subroutines you're in
and leave you in the 2-step SyncWait loop; if not, keep doing T 40 until
you are. If you're at the TST instruction, do one more T to get to the
branch instruction. Then do PC=PC+2;G to exit the loop.
You may need to repeat this process one or more times to regain control.
Once you have control, go straight to the Finder and to a Restart before
the driver can bite you again.
No guarantees and YMMV. However, 90% of the tine this lets be save my work
:-|
- -----------------------------------------------------
Richard Buckle
richardb@cocytus.demon.co.uk
Using this darned fine NewsHopper thingy.
+++++++++++++++++++++++++++
>From quinn@cs.uwa.edu.au (Quinn "The Eskimo!")
Date: Fri, 28 Oct 1994 10:13:36 +0800
Organization: Department of Computer Science, The University of Western Australia
In article <walkerj-1710942341460001@192.0.2.1>,
walkerj@math.scarolina.edu (James W. Walker) wrote:
>I guess I didn't make it clear in my original post, but it's not *my* code
>that gets stuck in SyncWait. It's usually Internet apps like Anarchie.
For reliable program (like Anarchie :) disappearing into SyncWait normally
means that your networking on your machine is stuffed up somehow.
To get out try this in MacsBug...
sm a0+10 ffff
g
What it does is set the ioResult field of the paramblock to -1, indicating
an error. You often have to do it a *lot* of times before it comes back
and often it doesn't work at all. But it makes you feel like you've got
control (:
Share and Enjoy.
--
Quinn "The Eskimo!" "I wasn't the one who fired the heat seeking
population annihilator out the window!"
Amaze your friends! Learn some cool MacsBug or MicroBug commands today (:
+++++++++++++++++++++++++++
>From devon_hubbard@taligent.com (Devon Hubbard)
Date: Fri, 28 Oct 1994 16:20:48 GMT
Organization: Taligent, Inc.
In article <quinn-2810941013360001@mac168.cs.uwa.oz.au>,
quinn@cs.uwa.edu.au (Quinn "The Eskimo!") wrote:
>In article <walkerj-1710942341460001@192.0.2.1>,
>walkerj@math.scarolina.edu (James W. Walker) wrote:
>
>>I guess I didn't make it clear in my original post, but it's not *my* code
>>that gets stuck in SyncWait. It's usually Internet apps like Anarchie.
>
>For reliable program (like Anarchie :) disappearing into SyncWait normally
>means that your networking on your machine is stuffed up somehow.
>
>To get out try this in MacsBug...
>
> sm a0+10 ffff
> g
>
>What it does is set the ioResult field of the paramblock to -1, indicating
>an error. You often have to do it a *lot* of times before it comes back
>and often it doesn't work at all. But it makes you feel like you've got
>control (:
Ouch! OUCH! This is assuming that reg A0 really points to the
cntrlParamBlockRec, which I hate to say doesn't always! I recently ran
into a vSyncWait problem (on an 8100av) that lead to fingering the
offending driver by looking at the data moved off D2 and matching that as
a DCE entry with the help of Macsbug's 'drvr' dcmd. In every case of
vSyncWait hang, a0 WAS NOT pointing to a valid paramblock so do a
dm a0 cntrlparamblockrec
before the 'sm' and make sure it looks like a valid paramblock, or you'll
surely be rebooting thereafter.
dEVoN
- -----------------------------------------------------------------------
Devon Hubbard Silicon Pilot
devon_hubbard@taligent.com Taligent, Inc
---------------------------
>From macrshap@bbn.com (Richard Shapiro)
Subject: having trouble with AEInteractWithUser & drag manager
Date: 9 Oct 1994 17:09:27 GMT
Organization: Bolt, Beranek and Newman Inc.
I'm in the process of adding some drag-support to an application. It's
working ok when the application is selected, so the underlying drag
management seems fine. But usually, I want to drag when another
application is selected (ie I'll be dragging from that other application).
In this case, when my app receives the drag, it needs to interact with the
user before proceeding. This is where I'm stuck.
I've set the InteractionAllowed flag to kAEInteractWithLocal (the default,
I know, but I thought I'd be explicit), and I carefully call
AEInteractWithUser before attempting any interaction. I'm calling it
without a timeout (kNoTimeOut), without a notification rec (should be OK
since I have the relevant BNDL, FREF and ICN# resources defined), and with
a very simple idle procedure which essentially does nothing (since at the
moment nothing in my app cares about update or activate events).
What I expected to happen was the usual flashing in the
current-application icon (on the right edge of the menubar), which would
allow me to bring my app to the front. What actually happens is...nothing:
no flashing, no process paying attention to mouse clicks, hence no way to
select my application (which has received the drop and is waiting in the
call to AEInteractWithUser) so that I can interact with it. All I can do
is cmd-opt-escape to force a quit.
What am I doing wrong? I'm assuming it must be one of two things: either
it's illegal to have user interaction after receiving a drop but before
acknowledging receipt; or I need to handle something in my idle function
which I'm not currently handling.
Any suggestions? If it matters, I'm using CW 4.5 C, and running System 7.1
on a q660av with drag extensions and the drag-ware Finder (7.1.3). The
drag flavors I'm handling at the moment are 'hfs ' and 'TEXT'.
Please copy followups to email -- thanks.
--
rs/macrshap@bbn.com
+++++++++++++++++++++++++++
>From Jens Alfke <jens_alfke@powertalk.apple.com>
Date: Mon, 10 Oct 1994 22:12:55 GMT
Organization: Apple Computer
Richard Shapiro, macrshap@bbn.com writes:
> What am I doing wrong? I'm assuming it must be one of two things: either
> it's illegal to have user interaction after receiving a drop but before
> acknowledging receipt
Bingo -- more specifically, it's illegal to cause a process switch while
inside a drag handler, since the drag handlers are called via a lightweight
process switch that is not compatible with the regular kind of process
switch. While you're in a drag handler, WNE is hacked to do nothing for
compatibility, but other ways to interact (such as calling AEInteractWithUser
or SetFrontProcess) will choke your machine.
Moral: Wait until after the drag finishes to try to interact with the user.
--Jens Alfke jens_alfke@powertalk.apple.com
"A man, a plan, a yam, a can of Spam ... Bananama!"
+++++++++++++++++++++++++++
>From macrshap@bbn.com (Richard Shapiro)
Date: 11 Oct 1994 01:54:10 GMT
Organization: Bolt, Beranek and Newman Inc.
In article <1994Oct10.221255.26429@gallant.apple.com>, Jens Alfke
<jens_alfke@powertalk.apple.com> wrote:
> Bingo -- more specifically, it's illegal to cause a process switch while
> inside a drag handler, since the drag handlers are called via a lightweight
> process switch that is not compatible with the regular kind of process
> switch. While you're in a drag handler, WNE is hacked to do nothing for
> compatibility, but other ways to interact (such as calling AEInteractWithUser
> or SetFrontProcess) will choke your machine.
>
> Moral: Wait until after the drag finishes to try to interact with the user.
OK, I eventually came to that conclusion myself. I guess it's good to have
it validated...
Problem is, I really need user interaction to complete the processing of
the drop. So, I tried to get around it by stashing the DragReference in a
global, setting a flag, returning from the handler, and then dealing with
the stashed DragReference when I'm back in the main event loop (depending
on the flag, of course). This doesn't work either. I can interact with the
user, but it looks as though the information associated with the
DragReference vanishes once the handler is exited. At least, I can't get
CountDragItems and the like to work properly outside the handler context.
Are these supposed to work outside the handler?
That seems to leave me with one final option: I have to get *all* the data
out of the DragReference while I'm in the handler, stash the whole pile
somewhere, exit the handler, and process the data later. Yucch, that's
pretty awful. Is there another possibility I'm missing here?
For now, I "fixed" the application to run without user-interaction when it
isn't in the foreground (which can only happen as a result of a drop).
It's better than nothing, but really not what I want...
--
rs/macrshap@bbn.com
+++++++++++++++++++++++++++
>From Jens Alfke <jens_alfke@powertalk.apple.com>
Date: Tue, 11 Oct 1994 17:28:36 GMT
Organization: Apple Computer
Richard Shapiro, macrshap@bbn.com writes:
> That seems to leave me with one final option: I have to get *all* the data
> out of the DragReference while I'm in the handler, stash the whole pile
> somewhere, exit the handler, and process the data later. Yucch, that's
> pretty awful. Is there another possibility I'm missing here?
Since you can't possibly use the DragReference after the sender disposes of
it, I think this is your only option. Is it that bad? Get the data you want
to use, stash it somewhere temporary, and when you get back into your event
loop ask the user what to do with it.
--Jens Alfke jens_alfke@powertalk.apple.com
"A man, a plan, a yam, a can of Spam ... Bananama!"
+++++++++++++++++++++++++++
>From macrshap@bbn.com (Richard Shapiro)
Date: 11 Oct 1994 22:25:03 GMT
Organization: Bolt, Beranek and Newman Inc.
In article <1994Oct11.172836.17257@gallant.apple.com>, Jens Alfke
<jens_alfke@powertalk.apple.com> wrote:
> Since you can't possibly use the DragReference after the sender disposes of
> it
As expected.
> I think this is your only option. Is it that bad? Get the data you want
> to use, stash it somewhere temporary, and when you get back into your event
> loop ask the user what to do with it.
No, it's not as bad as I thought. In fact it's already done and the result
is cleaner than my original plan :)
Now on to my next drag-manager question: receiving promise-hfs drags in an
application other than the Finder. Details in another posting...
--
rs/macrshap@bbn.com
+++++++++++++++++++++++++++
>From leonardr@netcom.com (Leonard Rosenthol)
Date: Wed, 19 Oct 1994 22:01:35 GMT
Organization: Aladdin Systems, Inc.
In article <macrshap-1110941825500001@ipa.bbn.com>, macrshap@bbn.com
(Richard Shapiro) wrote:
> > I think this is your only option. Is it that bad? Get the data you want
> > to use, stash it somewhere temporary, and when you get back into your event
> > loop ask the user what to do with it.
>
> No, it's not as bad as I thought. In fact it's already done and the result
> is cleaner than my original plan :)
>
What I've been doing in this case is to get all the info from the Drag,
and then send it back to myself in an Apple event (but NOT in sendToSelf
mode). This works quite nicely...
Leonard
- ------------------------------------------------------------------------
Leonard Rosenthol Internet: leonardr@netcom.com
Director of Advanced Technology AppleLink: MACgician
Aladdin Systems, Inc. GEnie: MACgician
+++++++++++++++++++++++++++
>From jonpugh@netcom.com (Jon Pugh)
Date: Wed, 26 Oct 1994 07:08:53 GMT
Organization: Will hack for food
Leonard Rosenthol (leonardr@netcom.com) wrote:
> What I've been doing in this case is to get all the info from the Drag,
> and then send it back to myself in an Apple event (but NOT in sendToSelf
> mode). This works quite nicely...
I actually send the event twice. Once to myself as record only, and then
again with signature addressing so that it goes through the event loop.
That way you can record the event too.
Jon
---------------------------
End of C.S.M.P. Digest
**********************